@apollo/client 4.3.3 → 4.3.5
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 +30 -0
- package/__cjs/cache/core/cache.cjs +1 -1
- package/__cjs/cache/core/cache.cjs.map +1 -1
- package/__cjs/cache/core/cache.d.cts +4 -1
- package/__cjs/cache/core/types/Cache.d.cts +5 -0
- package/__cjs/cache/inmemory/entityStore.cjs +4 -4
- package/__cjs/cache/inmemory/helpers.cjs +5 -0
- package/__cjs/cache/inmemory/helpers.cjs.map +1 -1
- package/__cjs/cache/inmemory/inMemoryCache.cjs +17 -6
- package/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
- package/__cjs/cache/inmemory/inMemoryCache.d.cts +3 -1
- package/__cjs/cache/inmemory/key-extractor.cjs +15 -3
- package/__cjs/cache/inmemory/key-extractor.cjs.map +1 -1
- package/__cjs/cache/inmemory/policies.cjs +21 -5
- package/__cjs/cache/inmemory/policies.cjs.map +1 -1
- package/__cjs/cache/inmemory/policies.d.cts +2 -0
- package/__cjs/cache/inmemory/readFromStore.cjs +28 -10
- package/__cjs/cache/inmemory/readFromStore.cjs.map +1 -1
- package/__cjs/cache/inmemory/types.d.cts +7 -2
- package/__cjs/cache/inmemory/writeToStore.cjs +32 -16
- package/__cjs/cache/inmemory/writeToStore.cjs.map +1 -1
- package/__cjs/cache/inmemory/writeToStore.d.cts +5 -2
- package/__cjs/core/ApolloClient.cjs +14 -14
- package/__cjs/core/ObservableQuery.cjs +8 -8
- package/__cjs/core/QueryInfo.cjs +22 -33
- package/__cjs/core/QueryInfo.cjs.map +1 -1
- package/__cjs/core/QueryInfo.d.cts +1 -1
- package/__cjs/core/QueryManager.cjs +22 -15
- package/__cjs/core/QueryManager.cjs.map +1 -1
- package/__cjs/core/RefetchEventManager.cjs +3 -3
- package/__cjs/incremental/handlers/defer20220824.cjs +15 -2
- package/__cjs/incremental/handlers/defer20220824.cjs.map +1 -1
- package/__cjs/incremental/handlers/defer20220824.d.cts +5 -1
- package/__cjs/incremental/handlers/graphql17Alpha9.cjs +58 -14
- package/__cjs/incremental/handlers/graphql17Alpha9.cjs.map +1 -1
- package/__cjs/incremental/handlers/graphql17Alpha9.d.cts +23 -12
- package/__cjs/incremental/handlers/notImplemented.cjs +1 -1
- package/__cjs/incremental/types.d.cts +19 -1
- package/__cjs/invariantErrorCodes.cjs +64 -58
- package/__cjs/react/hooks/useFragment.cjs.map +1 -1
- package/__cjs/react/hooks/useFragment.d.cts +42 -43
- 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/cache/core/cache.d.ts +4 -1
- package/cache/core/cache.js +1 -1
- package/cache/core/cache.js.map +1 -1
- package/cache/core/types/Cache.d.ts +5 -0
- package/cache/core/types/Cache.js.map +1 -1
- package/cache/inmemory/entityStore.js +4 -4
- package/cache/inmemory/helpers.js +5 -0
- package/cache/inmemory/helpers.js.map +1 -1
- package/cache/inmemory/inMemoryCache.d.ts +3 -1
- package/cache/inmemory/inMemoryCache.js +17 -6
- package/cache/inmemory/inMemoryCache.js.map +1 -1
- package/cache/inmemory/key-extractor.js +15 -3
- package/cache/inmemory/key-extractor.js.map +1 -1
- package/cache/inmemory/policies.d.ts +2 -0
- package/cache/inmemory/policies.js +22 -6
- package/cache/inmemory/policies.js.map +1 -1
- package/cache/inmemory/readFromStore.js +28 -10
- package/cache/inmemory/readFromStore.js.map +1 -1
- package/cache/inmemory/types.d.ts +7 -2
- package/cache/inmemory/types.js.map +1 -1
- package/cache/inmemory/writeToStore.d.ts +5 -2
- package/cache/inmemory/writeToStore.js +33 -17
- package/cache/inmemory/writeToStore.js.map +1 -1
- package/core/ApolloClient.js +14 -14
- package/core/ObservableQuery.js +8 -8
- package/core/QueryInfo.d.ts +1 -1
- package/core/QueryInfo.js +23 -34
- package/core/QueryInfo.js.map +1 -1
- package/core/QueryManager.js +22 -15
- package/core/QueryManager.js.map +1 -1
- package/core/RefetchEventManager.js +3 -3
- package/incremental/handlers/defer20220824.d.ts +5 -1
- package/incremental/handlers/defer20220824.js +15 -2
- package/incremental/handlers/defer20220824.js.map +1 -1
- package/incremental/handlers/graphql17Alpha9.d.ts +23 -12
- package/incremental/handlers/graphql17Alpha9.js +58 -14
- package/incremental/handlers/graphql17Alpha9.js.map +1 -1
- package/incremental/handlers/notImplemented.js +1 -1
- package/incremental/types.d.ts +19 -1
- package/incremental/types.js.map +1 -1
- package/invariantErrorCodes.js +64 -58
- package/package.json +1 -1
- package/react/hooks/useFragment.d.ts +42 -43
- package/react/hooks/useFragment.js.map +1 -1
- package/react/hooks-compiled/useFragment.d.ts +42 -43
- package/react/hooks-compiled/useFragment.js.map +1 -1
- package/utilities/internal/index.d.ts +0 -1
- package/utilities/internal/index.js.map +1 -1
- package/version.js +1 -1
- package/__cjs/utilities/internal/types/DeferInfo.cjs +0 -3
- package/__cjs/utilities/internal/types/DeferInfo.cjs.map +0 -1
- package/__cjs/utilities/internal/types/DeferInfo.d.cts +0 -10
- package/utilities/internal/types/DeferInfo.d.ts +0 -10
- package/utilities/internal/types/DeferInfo.js +0 -2
- package/utilities/internal/types/DeferInfo.js.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { DocumentNode, FieldNode } from "graphql";
|
|
2
2
|
import type { OperationVariables } from "@apollo/client";
|
|
3
|
+
import type { Incremental } from "@apollo/client/incremental";
|
|
3
4
|
import type { Reference, StoreObject, StoreValue } from "@apollo/client/utilities";
|
|
4
|
-
import type {
|
|
5
|
+
import type { ExtensionsWithStreamInfo, handleIncrementalSymbol, RemoveIndexSignature, StreamInfoTrie } from "@apollo/client/utilities/internal";
|
|
5
6
|
import type { ApolloCache, Transaction } from "../core/cache.js";
|
|
6
7
|
import type { AllFieldsModifier, CanReadFunction, Modifiers, ToReferenceFunction } from "../core/types/common.js";
|
|
7
8
|
import type { FieldValueGetter } from "./entityStore.js";
|
|
@@ -86,7 +87,10 @@ export type ReadQueryOptions = {
|
|
|
86
87
|
*/
|
|
87
88
|
export interface DiffIncrementalInfo {
|
|
88
89
|
streamInfo?: StreamInfoTrie;
|
|
89
|
-
|
|
90
|
+
isDeferPending?: (path: Incremental.Path, label: string | undefined) => boolean;
|
|
91
|
+
}
|
|
92
|
+
export interface WithHandleIncremental {
|
|
93
|
+
[handleIncrementalSymbol]?: DiffIncrementalInfo | undefined;
|
|
90
94
|
}
|
|
91
95
|
export type DiffQueryAgainstStoreOptions = ReadQueryOptions & {
|
|
92
96
|
returnPartialData?: boolean;
|
|
@@ -128,6 +132,7 @@ export interface ReadMergeModifyContext {
|
|
|
128
132
|
variables?: OperationVariables;
|
|
129
133
|
varString?: string;
|
|
130
134
|
extensions?: ExtensionsWithStreamInfo;
|
|
135
|
+
isDeferPending?: (path: Incremental.Path, label: string | undefined) => boolean;
|
|
131
136
|
}
|
|
132
137
|
type ListOf<T extends string> = `[${T}]`;
|
|
133
138
|
type NestedScalarName<T extends string> = T | ListOf<T> | ListOf<ListOf<T>> | ListOf<ListOf<ListOf<T>>> | ListOf<ListOf<ListOf<ListOf<T>>>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/cache/inmemory/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentNode, FieldNode } from \"graphql\";\n\nimport type { OperationVariables } from \"@apollo/client\";\nimport type {\n Reference,\n StoreObject,\n StoreValue,\n} from \"@apollo/client/utilities\";\nimport type {\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/cache/inmemory/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentNode, FieldNode } from \"graphql\";\n\nimport type { OperationVariables } from \"@apollo/client\";\nimport type { Incremental } from \"@apollo/client/incremental\";\nimport type {\n Reference,\n StoreObject,\n StoreValue,\n} from \"@apollo/client/utilities\";\nimport type {\n ExtensionsWithStreamInfo,\n handleIncrementalSymbol,\n RemoveIndexSignature,\n StreamInfoTrie,\n} from \"@apollo/client/utilities/internal\";\n\nimport type { ApolloCache, Transaction } from \"../core/cache.js\";\nimport type {\n AllFieldsModifier,\n CanReadFunction,\n Modifiers,\n ToReferenceFunction,\n} from \"../core/types/common.js\";\n\nimport type { FieldValueGetter } from \"./entityStore.js\";\nimport type { FragmentRegistryAPI } from \"./fragmentRegistry.js\";\nimport type { InMemoryCache } from \"./inMemoryCache.js\";\nimport type {\n FieldMergeFunction,\n KeyFieldsFunction,\n PossibleTypesMap,\n StorageType,\n TypePolicies,\n} from \"./policies.js\";\n\nexport type { Reference, StoreObject, StoreValue };\n\nexport interface IdGetterObj extends Object {\n __typename?: string;\n id?: string;\n _id?: string;\n}\n\nexport declare type IdGetter = (value: IdGetterObj) => string | undefined;\n\n/**\n * This is an interface used to access, set and remove\n * StoreObjects from the cache\n */\nexport interface NormalizedCache {\n has(dataId: string): boolean;\n get(dataId: string, fieldName: string): StoreValue;\n\n // The store.merge method allows either argument to be a string ID, but\n // the other argument has to be a StoreObject. Either way, newer fields\n // always take precedence over older fields.\n merge(olderId: string, newerObject: StoreObject): void;\n merge(olderObject: StoreObject, newerId: string): void;\n\n modify<Entity extends Record<string, any>>(\n dataId: string,\n fields: Modifiers<Entity> | AllFieldsModifier<Entity>,\n exact: boolean\n ): boolean;\n delete(dataId: string, fieldName?: string): boolean;\n clear(): void;\n\n // non-Map elements:\n /**\n * returns an Object with key-value pairs matching the contents of the store\n */\n toObject(): NormalizedCacheObject;\n /**\n * replace the state of the store\n */\n replace(newData: NormalizedCacheObject): void;\n\n /**\n * Retain (or release) a given root ID to protect (or expose) it and its\n * transitive child entities from (or to) garbage collection. The current\n * retainment count is returned by both methods. Note that releasing a root\n * ID does not cause that entity to be garbage collected, but merely removes\n * it from the set of root IDs that will be considered during the next\n * mark-and-sweep collection.\n */\n retain(rootId: string): number;\n release(rootId: string): number;\n\n getFieldValue: FieldValueGetter;\n toReference: ToReferenceFunction;\n canRead: CanReadFunction;\n\n getStorage(\n idOrObj: string | StoreObject,\n ...storeFieldNames: (string | number)[]\n ): StorageType;\n}\n\n/**\n * This is a normalized representation of the Apollo query result cache. It consists of\n * a flattened representation of query result trees.\n */\nexport interface NormalizedCacheObject {\n __META?: {\n // Well-known singleton IDs like ROOT_QUERY and ROOT_MUTATION are\n // always considered to be root IDs during cache.gc garbage\n // collection, but other IDs can become roots if they are written\n // directly with cache.writeFragment or retained explicitly with\n // cache.retain. When such IDs exist, we include them in the __META\n // section so that they can survive cache.{extract,restore}.\n extraRootIds: string[];\n };\n [dataId: string]: StoreObject | undefined;\n}\n\nexport type OptimisticStoreItem = {\n id: string;\n data: NormalizedCacheObject;\n transaction: Transaction;\n};\n\nexport type ReadQueryOptions = {\n /**\n * The Apollo Client store object.\n */\n store: NormalizedCache;\n /**\n * A parsed GraphQL query document.\n */\n query: DocumentNode;\n variables?: Object;\n previousResult?: any;\n rootId?: string;\n config?: ApolloReducerConfig;\n};\n\n/** @internal */\nexport interface DiffIncrementalInfo {\n streamInfo?: StreamInfoTrie;\n isDeferPending?: (\n path: Incremental.Path,\n label: string | undefined\n ) => boolean;\n}\n\nexport interface WithHandleIncremental {\n [handleIncrementalSymbol]?: DiffIncrementalInfo | undefined;\n}\n\nexport type DiffQueryAgainstStoreOptions = ReadQueryOptions & {\n returnPartialData?: boolean;\n};\n\nexport type ApolloReducerConfig = {\n dataIdFromObject?: KeyFieldsFunction;\n};\n\nexport interface InputObjectConfig {\n fields: Record<string, string>;\n}\n\nexport interface InputObjectsOption {\n [inputObjectName: string]: InputObjectConfig;\n}\n\nexport type InMemoryCacheConfig = ApolloReducerConfig & {\n resultCaching?: boolean;\n possibleTypes?: PossibleTypesMap;\n typePolicies?: TypePolicies;\n fragments?: FragmentRegistryAPI;\n inputObjects?: InputObjectsOption;\n} & ({} extends InMemoryCache.ScalarsOption ?\n InMemoryCache.ScalarsOption extends Record<string, never> ?\n {\n scalars?: Record<\n string,\n `Scalar types must be declared in ApolloCache.Scalars before usage. See https://www.apollographql.com/docs/react/data/typescript#declaring-scalar-types.`\n >;\n }\n : { scalars?: InMemoryCache.ScalarsOption }\n : { scalars: InMemoryCache.ScalarsOption });\n\nexport interface MergeInfo {\n field: FieldNode;\n typename: string | undefined;\n merge: FieldMergeFunction;\n path: Array<string | number>;\n}\n\nexport interface MergeTree {\n info?: MergeInfo;\n map: Map<string | number, MergeTree>;\n}\n\nexport interface ReadMergeModifyContext {\n store: NormalizedCache;\n variables?: OperationVariables;\n // A JSON.stringify-serialized version of context.variables.\n varString?: string;\n extensions?: ExtensionsWithStreamInfo;\n isDeferPending?: (\n path: Incremental.Path,\n label: string | undefined\n ) => boolean;\n}\n\ntype ListOf<T extends string> = `[${T}]`;\n\ntype NestedScalarName<T extends string> =\n | T\n | ListOf<T>\n | ListOf<ListOf<T>>\n | ListOf<ListOf<ListOf<T>>>\n | ListOf<ListOf<ListOf<ListOf<T>>>>;\n\nexport type KnownScalars = RemoveIndexSignature<ApolloCache.Scalars>;\n\nexport type ScalarType =\n | NestedScalarName<keyof KnownScalars & string>\n | (string extends keyof ApolloCache.Scalars ? string & {} : never);\n"]}
|
|
@@ -2,9 +2,10 @@ import type { FieldNode, SelectionSetNode } from "graphql";
|
|
|
2
2
|
import type { Cache, OperationVariables } from "@apollo/client";
|
|
3
3
|
import type { Reference, StoreObject } from "@apollo/client/utilities";
|
|
4
4
|
import type { FragmentMap, FragmentMapFunction } from "@apollo/client/utilities/internal";
|
|
5
|
+
import { handleIncrementalSymbol } from "@apollo/client/utilities/internal";
|
|
5
6
|
import type { InMemoryCache } from "./inMemoryCache.js";
|
|
6
7
|
import type { StoreReader } from "./readFromStore.js";
|
|
7
|
-
import type { InMemoryCacheConfig, MergeTree, NormalizedCache, ReadMergeModifyContext } from "./types.js";
|
|
8
|
+
import type { DiffIncrementalInfo, InMemoryCacheConfig, MergeTree, NormalizedCache, ReadMergeModifyContext } from "./types.js";
|
|
8
9
|
export interface WriteContext extends ReadMergeModifyContext {
|
|
9
10
|
readonly written: {
|
|
10
11
|
[dataId: string]: SelectionSetNode[];
|
|
@@ -28,7 +29,9 @@ export declare class StoreWriter {
|
|
|
28
29
|
private reader?;
|
|
29
30
|
private fragments?;
|
|
30
31
|
constructor(cache: InMemoryCache, reader?: StoreReader | undefined, fragments?: InMemoryCacheConfig["fragments"]);
|
|
31
|
-
writeToStore<TData = unknown, TVariables extends OperationVariables = OperationVariables>(store: NormalizedCache, { query, result, dataId, variables, overwrite, extensions, }: Cache.WriteOptions<TData, TVariables>
|
|
32
|
+
writeToStore<TData = unknown, TVariables extends OperationVariables = OperationVariables>(store: NormalizedCache, { query, result, dataId, variables, overwrite, extensions, [handleIncrementalSymbol]: incrementalInfo, }: Cache.WriteOptions<TData, TVariables> & {
|
|
33
|
+
[handleIncrementalSymbol]?: DiffIncrementalInfo;
|
|
34
|
+
}): Reference | undefined;
|
|
32
35
|
private processSelectionSet;
|
|
33
36
|
private processFieldValue;
|
|
34
37
|
private flattenFields;
|
|
@@ -3,7 +3,7 @@ import { Trie } from "@wry/trie";
|
|
|
3
3
|
import { Kind } from "graphql";
|
|
4
4
|
import { addTypenameToDocument, canonicalStringify, isReference, } from "@apollo/client/utilities";
|
|
5
5
|
import { __DEV__ } from "@apollo/client/utilities/environment";
|
|
6
|
-
import { argumentsObjectFromField, cloneDeep, getDefaultValues, getFragmentFromSelection, getOperationDefinition, isArray, isField, isNonEmptyArray, isStreamField, makeReference, resultKeyNameFromField, shouldInclude, streamInfoSymbol, } from "@apollo/client/utilities/internal";
|
|
6
|
+
import { argumentsObjectFromField, cloneDeep, getDefaultValues, getFragmentFromSelection, getOperationDefinition, handleIncrementalSymbol, isArray, isField, isNonEmptyArray, isStreamField, makeReference, resultKeyNameFromField, shouldInclude, streamInfoSymbol, } from "@apollo/client/utilities/internal";
|
|
7
7
|
import { invariant, newInvariantError, } from "@apollo/client/utilities/invariant";
|
|
8
8
|
import { extractFragmentContext, fieldNameFromStoreName, makeProcessedFieldsMerger, storeValueIsStoreObject, } from "./helpers.js";
|
|
9
9
|
import { defaultStreamFieldMergeFn, normalizeReadFieldOptions, } from "./policies.js";
|
|
@@ -36,7 +36,7 @@ export class StoreWriter {
|
|
|
36
36
|
this.reader = reader;
|
|
37
37
|
this.fragments = fragments;
|
|
38
38
|
}
|
|
39
|
-
writeToStore(store, { query, result, dataId, variables, overwrite, extensions, }) {
|
|
39
|
+
writeToStore(store, { query, result, dataId, variables, overwrite, extensions, [handleIncrementalSymbol]: incrementalInfo, }) {
|
|
40
40
|
const operationDefinition = getOperationDefinition(query);
|
|
41
41
|
const merger = makeProcessedFieldsMerger();
|
|
42
42
|
variables = {
|
|
@@ -58,6 +58,7 @@ export class StoreWriter {
|
|
|
58
58
|
deferred: false,
|
|
59
59
|
flavors: new Map(),
|
|
60
60
|
extensions,
|
|
61
|
+
isDeferPending: incrementalInfo?.isDeferPending,
|
|
61
62
|
};
|
|
62
63
|
const ref = this.processSelectionSet({
|
|
63
64
|
result: result || {},
|
|
@@ -68,7 +69,7 @@ export class StoreWriter {
|
|
|
68
69
|
path: [],
|
|
69
70
|
});
|
|
70
71
|
if (!isReference(ref)) {
|
|
71
|
-
throw newInvariantError(
|
|
72
|
+
throw newInvariantError(123, result);
|
|
72
73
|
}
|
|
73
74
|
// So far, the store has not been modified, so now it's time to process
|
|
74
75
|
// context.incomingById and merge those incoming fields into context.store.
|
|
@@ -166,10 +167,10 @@ export class StoreWriter {
|
|
|
166
167
|
// This WriteContext will be the default context value for fields returned
|
|
167
168
|
// by the flattenFields method, but some fields may be assigned a modified
|
|
168
169
|
// context, depending on the presence of @client and other directives.
|
|
169
|
-
context, typename).forEach((context, field) => {
|
|
170
|
+
context, currentPath, typename).forEach((context, field) => {
|
|
170
171
|
const resultFieldKey = resultKeyNameFromField(field);
|
|
171
172
|
const value = result[resultFieldKey];
|
|
172
|
-
const path = [...currentPath,
|
|
173
|
+
const path = [...currentPath, resultFieldKey];
|
|
173
174
|
fieldNodeSet.add(field);
|
|
174
175
|
if (value !== void 0) {
|
|
175
176
|
const storeFieldName = policies.getStoreFieldName({
|
|
@@ -180,10 +181,15 @@ export class StoreWriter {
|
|
|
180
181
|
});
|
|
181
182
|
const childTree = getChildMergeTree(mergeTree, storeFieldName);
|
|
182
183
|
let incomingValue = this.processFieldValue(value, field,
|
|
183
|
-
// Reset context.clientOnly
|
|
184
|
-
//
|
|
184
|
+
// Reset context.clientOnly to its default value before processing
|
|
185
|
+
// nested selection sets, but inherit context.deferred: a resolved
|
|
186
|
+
// parent field must not erase the fact that an ancestor @defer
|
|
187
|
+
// boundary is still pending, or nested fields reached only through
|
|
188
|
+
// that ancestor will incorrectly be treated as complete and report
|
|
189
|
+
// spurious "Missing field" errors when their own boundary hasn't
|
|
190
|
+
// arrived yet.
|
|
185
191
|
field.selectionSet ?
|
|
186
|
-
getContextFlavor(context, false,
|
|
192
|
+
getContextFlavor(context, false, context.deferred)
|
|
187
193
|
: context, childTree, path);
|
|
188
194
|
// To determine if this field holds a child object with a merge function
|
|
189
195
|
// defined in its type policy (see PR #7070), we need to figure out the
|
|
@@ -230,7 +236,7 @@ export class StoreWriter {
|
|
|
230
236
|
// provide a default value, so its absence from the written data should
|
|
231
237
|
// not be cause for alarm.
|
|
232
238
|
!policies.getReadFunction(typename, field.name.value)) {
|
|
233
|
-
invariant.error(
|
|
239
|
+
invariant.error(124, resultKeyNameFromField(field), result);
|
|
234
240
|
}
|
|
235
241
|
});
|
|
236
242
|
// Identify the result object, even if dataId was already provided,
|
|
@@ -249,8 +255,9 @@ export class StoreWriter {
|
|
|
249
255
|
// Write any key fields that were used during identification, even if
|
|
250
256
|
// they were not mentioned in the original query.
|
|
251
257
|
if (keyObject) {
|
|
252
|
-
//
|
|
253
|
-
|
|
258
|
+
// Values in incoming take precedence over keyObject, which may contain
|
|
259
|
+
// serialized values used to compute the ID.
|
|
260
|
+
incoming = context.merge(keyObject, incoming);
|
|
254
261
|
}
|
|
255
262
|
}
|
|
256
263
|
catch (e) {
|
|
@@ -322,7 +329,7 @@ export class StoreWriter {
|
|
|
322
329
|
}
|
|
323
330
|
// Implements https://spec.graphql.org/draft/#sec-Field-Collection, but with
|
|
324
331
|
// some additions for tracking @client and @defer directives.
|
|
325
|
-
flattenFields(selectionSet, result, context, typename = getTypenameFromResult(result, selectionSet, context.fragmentMap)) {
|
|
332
|
+
flattenFields(selectionSet, result, context, path, typename = getTypenameFromResult(result, selectionSet, context.fragmentMap)) {
|
|
326
333
|
const fieldMap = new Map();
|
|
327
334
|
const { policies } = this.cache;
|
|
328
335
|
const limitingTrie = new Trie(false); // No need for WeakMap, since limitingTrie does not escape.
|
|
@@ -357,10 +364,19 @@ export class StoreWriter {
|
|
|
357
364
|
// @defer(if: false) does not make context.deferred false, but
|
|
358
365
|
// instead behaves as if there was no @defer directive.
|
|
359
366
|
if (!args || args.if !== false) {
|
|
360
|
-
|
|
367
|
+
// If we know (via context.isDeferPending) that this specific
|
|
368
|
+
// boundary has already been delivered, we don't need to mark
|
|
369
|
+
// it deferred, which allows fields under it to be validated
|
|
370
|
+
// normally instead of being silently exempted from the
|
|
371
|
+
// "Missing field" check below. When we can't determine
|
|
372
|
+
// whether the boundary is still pending (no callback, or the
|
|
373
|
+
// handler can't identify individual boundaries),
|
|
374
|
+
// conservatively assume it's still pending (`?? true`).
|
|
375
|
+
// `||=` (rather than `=`) preserves `deferred` if it was
|
|
376
|
+
// already true from an ancestor boundary.
|
|
377
|
+
deferred ||=
|
|
378
|
+
context.isDeferPending?.(path, args?.label) ?? true;
|
|
361
379
|
}
|
|
362
|
-
// TODO In the future, we may want to record args.label using
|
|
363
|
-
// context.deferred, if a label is specified.
|
|
364
380
|
}
|
|
365
381
|
});
|
|
366
382
|
}
|
|
@@ -378,7 +394,7 @@ export class StoreWriter {
|
|
|
378
394
|
else {
|
|
379
395
|
const fragment = getFragmentFromSelection(selection, context.lookupFragment);
|
|
380
396
|
if (!fragment && selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
381
|
-
throw newInvariantError(
|
|
397
|
+
throw newInvariantError(125, selection.name.value);
|
|
382
398
|
}
|
|
383
399
|
if (fragment &&
|
|
384
400
|
policies.fragmentMatches(fragment, typename, result, context.variables)) {
|
|
@@ -550,7 +566,7 @@ function warnAboutDataLoss(existingRef, incomingObj, storeFieldName, store) {
|
|
|
550
566
|
}
|
|
551
567
|
});
|
|
552
568
|
}
|
|
553
|
-
__DEV__ && invariant.warn(
|
|
569
|
+
__DEV__ && invariant.warn(126, fieldName, parentType, childTypenames.length ?
|
|
554
570
|
"either ensure all objects of type " +
|
|
555
571
|
childTypenames.join(" and ") +
|
|
556
572
|
" have an ID or a custom merge function, or "
|