UNPKG

31.5 kBJavaScriptView Raw
1import { __assign, __rest } from "tslib";
2import { invariant, newInvariantError } from "../../utilities/globals/index.js";
3import { storeKeyNameFromField, argumentsObjectFromField, isReference, getStoreKeyName, isNonNullObject, stringifyForDisplay, } from "../../utilities/index.js";
4import { hasOwn, fieldNameFromStoreName, storeValueIsStoreObject, selectionSetMatchesResult, TypeOrFieldNameRegExp, defaultDataIdFromObject, isArray, } from "./helpers.js";
5import { cacheSlot } from "./reactiveVars.js";
6import { keyArgsFnFromSpecifier, keyFieldsFnFromSpecifier, } from "./key-extractor.js";
7function argsFromFieldSpecifier(spec) {
8 return (spec.args !== void 0 ? spec.args
9 : spec.field ? argumentsObjectFromField(spec.field, spec.variables)
10 : null);
11}
12var nullKeyFieldsFn = function () { return void 0; };
13var simpleKeyArgsFn = function (_args, context) { return context.fieldName; };
14// These merge functions can be selected by specifying merge:true or
15// merge:false in a field policy.
16var mergeTrueFn = function (existing, incoming, _a) {
17 var mergeObjects = _a.mergeObjects;
18 return mergeObjects(existing, incoming);
19};
20var mergeFalseFn = function (_, incoming) { return incoming; };
21var Policies = /** @class */ (function () {
22 function Policies(config) {
23 this.config = config;
24 this.typePolicies = Object.create(null);
25 this.toBeAdded = Object.create(null);
26 // Map from subtype names to sets of supertype names. Note that this
27 // representation inverts the structure of possibleTypes (whose keys are
28 // supertypes and whose values are arrays of subtypes) because it tends
29 // to be much more efficient to search upwards than downwards.
30 this.supertypeMap = new Map();
31 // Any fuzzy subtypes specified by possibleTypes will be converted to
32 // RegExp objects and recorded here. Every key of this map can also be
33 // found in supertypeMap. In many cases this Map will be empty, which
34 // means no fuzzy subtype checking will happen in fragmentMatches.
35 this.fuzzySubtypes = new Map();
36 this.rootIdsByTypename = Object.create(null);
37 this.rootTypenamesById = Object.create(null);
38 this.usingPossibleTypes = false;
39 this.config = __assign({ dataIdFromObject: defaultDataIdFromObject }, config);
40 this.cache = this.config.cache;
41 this.setRootTypename("Query");
42 this.setRootTypename("Mutation");
43 this.setRootTypename("Subscription");
44 if (config.possibleTypes) {
45 this.addPossibleTypes(config.possibleTypes);
46 }
47 if (config.typePolicies) {
48 this.addTypePolicies(config.typePolicies);
49 }
50 }
51 Policies.prototype.identify = function (object, partialContext) {
52 var _a;
53 var policies = this;
54 var typename = (partialContext &&
55 (partialContext.typename || ((_a = partialContext.storeObject) === null || _a === void 0 ? void 0 : _a.__typename))) ||
56 object.__typename;
57 // It should be possible to write root Query fields with writeFragment,
58 // using { __typename: "Query", ... } as the data, but it does not make
59 // sense to allow the same identification behavior for the Mutation and
60 // Subscription types, since application code should never be writing
61 // directly to (or reading directly from) those root objects.
62 if (typename === this.rootTypenamesById.ROOT_QUERY) {
63 return ["ROOT_QUERY"];
64 }
65 // Default context.storeObject to object if not otherwise provided.
66 var storeObject = (partialContext && partialContext.storeObject) || object;
67 var context = __assign(__assign({}, partialContext), { typename: typename, storeObject: storeObject, readField: (partialContext && partialContext.readField) ||
68 function () {
69 var options = normalizeReadFieldOptions(arguments, storeObject);
70 return policies.readField(options, {
71 store: policies.cache["data"],
72 variables: options.variables,
73 });
74 } });
75 var id;
76 var policy = typename && this.getTypePolicy(typename);
77 var keyFn = (policy && policy.keyFn) || this.config.dataIdFromObject;
78 while (keyFn) {
79 var specifierOrId = keyFn(__assign(__assign({}, object), storeObject), context);
80 if (isArray(specifierOrId)) {
81 keyFn = keyFieldsFnFromSpecifier(specifierOrId);
82 }
83 else {
84 id = specifierOrId;
85 break;
86 }
87 }
88 id = id ? String(id) : void 0;
89 return context.keyObject ? [id, context.keyObject] : [id];
90 };
91 Policies.prototype.addTypePolicies = function (typePolicies) {
92 var _this = this;
93 Object.keys(typePolicies).forEach(function (typename) {
94 var _a = typePolicies[typename], queryType = _a.queryType, mutationType = _a.mutationType, subscriptionType = _a.subscriptionType, incoming = __rest(_a, ["queryType", "mutationType", "subscriptionType"]);
95 // Though {query,mutation,subscription}Type configurations are rare,
96 // it's important to call setRootTypename as early as possible,
97 // since these configurations should apply consistently for the
98 // entire lifetime of the cache. Also, since only one __typename can
99 // qualify as one of these root types, these three properties cannot
100 // be inherited, unlike the rest of the incoming properties. That
101 // restriction is convenient, because the purpose of this.toBeAdded
102 // is to delay the processing of type/field policies until the first
103 // time they're used, allowing policies to be added in any order as
104 // long as all relevant policies (including policies for supertypes)
105 // have been added by the time a given policy is used for the first
106 // time. In other words, since inheritance doesn't matter for these
107 // properties, there's also no need to delay their processing using
108 // the this.toBeAdded queue.
109 if (queryType)
110 _this.setRootTypename("Query", typename);
111 if (mutationType)
112 _this.setRootTypename("Mutation", typename);
113 if (subscriptionType)
114 _this.setRootTypename("Subscription", typename);
115 if (hasOwn.call(_this.toBeAdded, typename)) {
116 _this.toBeAdded[typename].push(incoming);
117 }
118 else {
119 _this.toBeAdded[typename] = [incoming];
120 }
121 });
122 };
123 Policies.prototype.updateTypePolicy = function (typename, incoming) {
124 var _this = this;
125 var existing = this.getTypePolicy(typename);
126 var keyFields = incoming.keyFields, fields = incoming.fields;
127 function setMerge(existing, merge) {
128 existing.merge =
129 typeof merge === "function" ? merge
130 // Pass merge:true as a shorthand for a merge implementation
131 // that returns options.mergeObjects(existing, incoming).
132 : merge === true ? mergeTrueFn
133 // Pass merge:false to make incoming always replace existing
134 // without any warnings about data clobbering.
135 : merge === false ? mergeFalseFn
136 : existing.merge;
137 }
138 // Type policies can define merge functions, as an alternative to
139 // using field policies to merge child objects.
140 setMerge(existing, incoming.merge);
141 existing.keyFn =
142 // Pass false to disable normalization for this typename.
143 keyFields === false ? nullKeyFieldsFn
144 // Pass an array of strings to use those fields to compute a
145 // composite ID for objects of this typename.
146 : isArray(keyFields) ? keyFieldsFnFromSpecifier(keyFields)
147 // Pass a function to take full control over identification.
148 : typeof keyFields === "function" ? keyFields
149 // Leave existing.keyFn unchanged if above cases fail.
150 : existing.keyFn;
151 if (fields) {
152 Object.keys(fields).forEach(function (fieldName) {
153 var existing = _this.getFieldPolicy(typename, fieldName, true);
154 var incoming = fields[fieldName];
155 if (typeof incoming === "function") {
156 existing.read = incoming;
157 }
158 else {
159 var keyArgs = incoming.keyArgs, read = incoming.read, merge = incoming.merge;
160 existing.keyFn =
161 // Pass false to disable argument-based differentiation of
162 // field identities.
163 keyArgs === false ? simpleKeyArgsFn
164 // Pass an array of strings to use named arguments to
165 // compute a composite identity for the field.
166 : isArray(keyArgs) ? keyArgsFnFromSpecifier(keyArgs)
167 // Pass a function to take full control over field identity.
168 : typeof keyArgs === "function" ? keyArgs
169 // Leave existing.keyFn unchanged if above cases fail.
170 : existing.keyFn;
171 if (typeof read === "function") {
172 existing.read = read;
173 }
174 setMerge(existing, merge);
175 }
176 if (existing.read && existing.merge) {
177 // If we have both a read and a merge function, assume
178 // keyArgs:false, because read and merge together can take
179 // responsibility for interpreting arguments in and out. This
180 // default assumption can always be overridden by specifying
181 // keyArgs explicitly in the FieldPolicy.
182 existing.keyFn = existing.keyFn || simpleKeyArgsFn;
183 }
184 });
185 }
186 };
187 Policies.prototype.setRootTypename = function (which, typename) {
188 if (typename === void 0) { typename = which; }
189 var rootId = "ROOT_" + which.toUpperCase();
190 var old = this.rootTypenamesById[rootId];
191 if (typename !== old) {
192 invariant(!old || old === which, 5, which);
193 // First, delete any old __typename associated with this rootId from
194 // rootIdsByTypename.
195 if (old)
196 delete this.rootIdsByTypename[old];
197 // Now make this the only __typename that maps to this rootId.
198 this.rootIdsByTypename[typename] = rootId;
199 // Finally, update the __typename associated with this rootId.
200 this.rootTypenamesById[rootId] = typename;
201 }
202 };
203 Policies.prototype.addPossibleTypes = function (possibleTypes) {
204 var _this = this;
205 this.usingPossibleTypes = true;
206 Object.keys(possibleTypes).forEach(function (supertype) {
207 // Make sure all types have an entry in this.supertypeMap, even if
208 // their supertype set is empty, so we can return false immediately
209 // from policies.fragmentMatches for unknown supertypes.
210 _this.getSupertypeSet(supertype, true);
211 possibleTypes[supertype].forEach(function (subtype) {
212 _this.getSupertypeSet(subtype, true).add(supertype);
213 var match = subtype.match(TypeOrFieldNameRegExp);
214 if (!match || match[0] !== subtype) {
215 // TODO Don't interpret just any invalid typename as a RegExp.
216 _this.fuzzySubtypes.set(subtype, new RegExp(subtype));
217 }
218 });
219 });
220 };
221 Policies.prototype.getTypePolicy = function (typename) {
222 var _this = this;
223 if (!hasOwn.call(this.typePolicies, typename)) {
224 var policy_1 = (this.typePolicies[typename] = Object.create(null));
225 policy_1.fields = Object.create(null);
226 // When the TypePolicy for typename is first accessed, instead of
227 // starting with an empty policy object, inherit any properties or
228 // fields from the type policies of the supertypes of typename.
229 //
230 // Any properties or fields defined explicitly within the TypePolicy
231 // for typename will take precedence, and if there are multiple
232 // supertypes, the properties of policies whose types were added
233 // later via addPossibleTypes will take precedence over those of
234 // earlier supertypes. TODO Perhaps we should warn about these
235 // conflicts in development, and recommend defining the property
236 // explicitly in the subtype policy?
237 //
238 // Field policy inheritance is atomic/shallow: you can't inherit a
239 // field policy and then override just its read function, since read
240 // and merge functions often need to cooperate, so changing only one
241 // of them would be a recipe for inconsistency.
242 //
243 // Once the TypePolicy for typename has been accessed, its properties can
244 // still be updated directly using addTypePolicies, but future changes to
245 // inherited supertype policies will not be reflected in this subtype
246 // policy, because this code runs at most once per typename.
247 var supertypes_1 = this.supertypeMap.get(typename);
248 if (!supertypes_1 && this.fuzzySubtypes.size) {
249 // To make the inheritance logic work for unknown typename strings that
250 // may have fuzzy supertypes, we give this typename an empty supertype
251 // set and then populate it with any fuzzy supertypes that match.
252 supertypes_1 = this.getSupertypeSet(typename, true);
253 // This only works for typenames that are directly matched by a fuzzy
254 // supertype. What if there is an intermediate chain of supertypes?
255 // While possible, that situation can only be solved effectively by
256 // specifying the intermediate relationships via possibleTypes, manually
257 // and in a non-fuzzy way.
258 this.fuzzySubtypes.forEach(function (regExp, fuzzy) {
259 if (regExp.test(typename)) {
260 // The fuzzy parameter is just the original string version of regExp
261 // (not a valid __typename string), but we can look up the
262 // associated supertype(s) in this.supertypeMap.
263 var fuzzySupertypes = _this.supertypeMap.get(fuzzy);
264 if (fuzzySupertypes) {
265 fuzzySupertypes.forEach(function (supertype) {
266 return supertypes_1.add(supertype);
267 });
268 }
269 }
270 });
271 }
272 if (supertypes_1 && supertypes_1.size) {
273 supertypes_1.forEach(function (supertype) {
274 var _a = _this.getTypePolicy(supertype), fields = _a.fields, rest = __rest(_a, ["fields"]);
275 Object.assign(policy_1, rest);
276 Object.assign(policy_1.fields, fields);
277 });
278 }
279 }
280 var inbox = this.toBeAdded[typename];
281 if (inbox && inbox.length) {
282 // Merge the pending policies into this.typePolicies, in the order they
283 // were originally passed to addTypePolicy.
284 inbox.splice(0).forEach(function (policy) {
285 _this.updateTypePolicy(typename, policy);
286 });
287 }
288 return this.typePolicies[typename];
289 };
290 Policies.prototype.getFieldPolicy = function (typename, fieldName, createIfMissing) {
291 if (typename) {
292 var fieldPolicies = this.getTypePolicy(typename).fields;
293 return (fieldPolicies[fieldName] ||
294 (createIfMissing && (fieldPolicies[fieldName] = Object.create(null))));
295 }
296 };
297 Policies.prototype.getSupertypeSet = function (subtype, createIfMissing) {
298 var supertypeSet = this.supertypeMap.get(subtype);
299 if (!supertypeSet && createIfMissing) {
300 this.supertypeMap.set(subtype, (supertypeSet = new Set()));
301 }
302 return supertypeSet;
303 };
304 Policies.prototype.fragmentMatches = function (fragment, typename, result, variables) {
305 var _this = this;
306 if (!fragment.typeCondition)
307 return true;
308 // If the fragment has a type condition but the object we're matching
309 // against does not have a __typename, the fragment cannot match.
310 if (!typename)
311 return false;
312 var supertype = fragment.typeCondition.name.value;
313 // Common case: fragment type condition and __typename are the same.
314 if (typename === supertype)
315 return true;
316 if (this.usingPossibleTypes && this.supertypeMap.has(supertype)) {
317 var typenameSupertypeSet = this.getSupertypeSet(typename, true);
318 var workQueue_1 = [typenameSupertypeSet];
319 var maybeEnqueue_1 = function (subtype) {
320 var supertypeSet = _this.getSupertypeSet(subtype, false);
321 if (supertypeSet &&
322 supertypeSet.size &&
323 workQueue_1.indexOf(supertypeSet) < 0) {
324 workQueue_1.push(supertypeSet);
325 }
326 };
327 // We need to check fuzzy subtypes only if we encountered fuzzy
328 // subtype strings in addPossibleTypes, and only while writing to
329 // the cache, since that's when selectionSetMatchesResult gives a
330 // strong signal of fragment matching. The StoreReader class calls
331 // policies.fragmentMatches without passing a result object, so
332 // needToCheckFuzzySubtypes is always false while reading.
333 var needToCheckFuzzySubtypes = !!(result && this.fuzzySubtypes.size);
334 var checkingFuzzySubtypes = false;
335 // It's important to keep evaluating workQueue.length each time through
336 // the loop, because the queue can grow while we're iterating over it.
337 for (var i = 0; i < workQueue_1.length; ++i) {
338 var supertypeSet = workQueue_1[i];
339 if (supertypeSet.has(supertype)) {
340 if (!typenameSupertypeSet.has(supertype)) {
341 if (checkingFuzzySubtypes) {
342 globalThis.__DEV__ !== false && invariant.warn(6, typename, supertype);
343 }
344 // Record positive results for faster future lookup.
345 // Unfortunately, we cannot safely cache negative results,
346 // because new possibleTypes data could always be added to the
347 // Policies class.
348 typenameSupertypeSet.add(supertype);
349 }
350 return true;
351 }
352 supertypeSet.forEach(maybeEnqueue_1);
353 if (needToCheckFuzzySubtypes &&
354 // Start checking fuzzy subtypes only after exhausting all
355 // non-fuzzy subtypes (after the final iteration of the loop).
356 i === workQueue_1.length - 1 &&
357 // We could wait to compare fragment.selectionSet to result
358 // after we verify the supertype, but this check is often less
359 // expensive than that search, and we will have to do the
360 // comparison anyway whenever we find a potential match.
361 selectionSetMatchesResult(fragment.selectionSet, result, variables)) {
362 // We don't always need to check fuzzy subtypes (if no result
363 // was provided, or !this.fuzzySubtypes.size), but, when we do,
364 // we only want to check them once.
365 needToCheckFuzzySubtypes = false;
366 checkingFuzzySubtypes = true;
367 // If we find any fuzzy subtypes that match typename, extend the
368 // workQueue to search through the supertypes of those fuzzy
369 // subtypes. Otherwise the for-loop will terminate and we'll
370 // return false below.
371 this.fuzzySubtypes.forEach(function (regExp, fuzzyString) {
372 var match = typename.match(regExp);
373 if (match && match[0] === typename) {
374 maybeEnqueue_1(fuzzyString);
375 }
376 });
377 }
378 }
379 }
380 return false;
381 };
382 Policies.prototype.hasKeyArgs = function (typename, fieldName) {
383 var policy = this.getFieldPolicy(typename, fieldName, false);
384 return !!(policy && policy.keyFn);
385 };
386 Policies.prototype.getStoreFieldName = function (fieldSpec) {
387 var typename = fieldSpec.typename, fieldName = fieldSpec.fieldName;
388 var policy = this.getFieldPolicy(typename, fieldName, false);
389 var storeFieldName;
390 var keyFn = policy && policy.keyFn;
391 if (keyFn && typename) {
392 var context = {
393 typename: typename,
394 fieldName: fieldName,
395 field: fieldSpec.field || null,
396 variables: fieldSpec.variables,
397 };
398 var args = argsFromFieldSpecifier(fieldSpec);
399 while (keyFn) {
400 var specifierOrString = keyFn(args, context);
401 if (isArray(specifierOrString)) {
402 keyFn = keyArgsFnFromSpecifier(specifierOrString);
403 }
404 else {
405 // If the custom keyFn returns a falsy value, fall back to
406 // fieldName instead.
407 storeFieldName = specifierOrString || fieldName;
408 break;
409 }
410 }
411 }
412 if (storeFieldName === void 0) {
413 storeFieldName =
414 fieldSpec.field ?
415 storeKeyNameFromField(fieldSpec.field, fieldSpec.variables)
416 : getStoreKeyName(fieldName, argsFromFieldSpecifier(fieldSpec));
417 }
418 // Returning false from a keyArgs function is like configuring
419 // keyArgs: false, but more dynamic.
420 if (storeFieldName === false) {
421 return fieldName;
422 }
423 // Make sure custom field names start with the actual field.name.value
424 // of the field, so we can always figure out which properties of a
425 // StoreObject correspond to which original field names.
426 return fieldName === fieldNameFromStoreName(storeFieldName) ? storeFieldName
427 : fieldName + ":" + storeFieldName;
428 };
429 Policies.prototype.readField = function (options, context) {
430 var objectOrReference = options.from;
431 if (!objectOrReference)
432 return;
433 var nameOrField = options.field || options.fieldName;
434 if (!nameOrField)
435 return;
436 if (options.typename === void 0) {
437 var typename = context.store.getFieldValue(objectOrReference, "__typename");
438 if (typename)
439 options.typename = typename;
440 }
441 var storeFieldName = this.getStoreFieldName(options);
442 var fieldName = fieldNameFromStoreName(storeFieldName);
443 var existing = context.store.getFieldValue(objectOrReference, storeFieldName);
444 var policy = this.getFieldPolicy(options.typename, fieldName, false);
445 var read = policy && policy.read;
446 if (read) {
447 var readOptions = makeFieldFunctionOptions(this, objectOrReference, options, context, context.store.getStorage(isReference(objectOrReference) ?
448 objectOrReference.__ref
449 : objectOrReference, storeFieldName));
450 // Call read(existing, readOptions) with cacheSlot holding this.cache.
451 return cacheSlot.withValue(this.cache, read, [
452 existing,
453 readOptions,
454 ]);
455 }
456 return existing;
457 };
458 Policies.prototype.getReadFunction = function (typename, fieldName) {
459 var policy = this.getFieldPolicy(typename, fieldName, false);
460 return policy && policy.read;
461 };
462 Policies.prototype.getMergeFunction = function (parentTypename, fieldName, childTypename) {
463 var policy = this.getFieldPolicy(parentTypename, fieldName, false);
464 var merge = policy && policy.merge;
465 if (!merge && childTypename) {
466 policy = this.getTypePolicy(childTypename);
467 merge = policy && policy.merge;
468 }
469 return merge;
470 };
471 Policies.prototype.runMergeFunction = function (existing, incoming, _a, context, storage) {
472 var field = _a.field, typename = _a.typename, merge = _a.merge;
473 if (merge === mergeTrueFn) {
474 // Instead of going to the trouble of creating a full
475 // FieldFunctionOptions object and calling mergeTrueFn, we can
476 // simply call mergeObjects, as mergeTrueFn would.
477 return makeMergeObjectsFunction(context.store)(existing, incoming);
478 }
479 if (merge === mergeFalseFn) {
480 // Likewise for mergeFalseFn, whose implementation is even simpler.
481 return incoming;
482 }
483 // If cache.writeQuery or cache.writeFragment was called with
484 // options.overwrite set to true, we still call merge functions, but
485 // the existing data is always undefined, so the merge function will
486 // not attempt to combine the incoming data with the existing data.
487 if (context.overwrite) {
488 existing = void 0;
489 }
490 return merge(existing, incoming, makeFieldFunctionOptions(this,
491 // Unlike options.readField for read functions, we do not fall
492 // back to the current object if no foreignObjOrRef is provided,
493 // because it's not clear what the current object should be for
494 // merge functions: the (possibly undefined) existing object, or
495 // the incoming object? If you think your merge function needs
496 // to read sibling fields in order to produce a new value for
497 // the current field, you might want to rethink your strategy,
498 // because that's a recipe for making merge behavior sensitive
499 // to the order in which fields are written into the cache.
500 // However, readField(name, ref) is useful for merge functions
501 // that need to deduplicate child objects and references.
502 void 0, {
503 typename: typename,
504 fieldName: field.name.value,
505 field: field,
506 variables: context.variables,
507 }, context, storage || Object.create(null)));
508 };
509 return Policies;
510}());
511export { Policies };
512function makeFieldFunctionOptions(policies, objectOrReference, fieldSpec, context, storage) {
513 var storeFieldName = policies.getStoreFieldName(fieldSpec);
514 var fieldName = fieldNameFromStoreName(storeFieldName);
515 var variables = fieldSpec.variables || context.variables;
516 var _a = context.store, toReference = _a.toReference, canRead = _a.canRead;
517 return {
518 args: argsFromFieldSpecifier(fieldSpec),
519 field: fieldSpec.field || null,
520 fieldName: fieldName,
521 storeFieldName: storeFieldName,
522 variables: variables,
523 isReference: isReference,
524 toReference: toReference,
525 storage: storage,
526 cache: policies.cache,
527 canRead: canRead,
528 readField: function () {
529 return policies.readField(normalizeReadFieldOptions(arguments, objectOrReference, variables), context);
530 },
531 mergeObjects: makeMergeObjectsFunction(context.store),
532 };
533}
534export function normalizeReadFieldOptions(readFieldArgs, objectOrReference, variables) {
535 var fieldNameOrOptions = readFieldArgs[0], from = readFieldArgs[1], argc = readFieldArgs.length;
536 var options;
537 if (typeof fieldNameOrOptions === "string") {
538 options = {
539 fieldName: fieldNameOrOptions,
540 // Default to objectOrReference only when no second argument was
541 // passed for the from parameter, not when undefined is explicitly
542 // passed as the second argument.
543 from: argc > 1 ? from : objectOrReference,
544 };
545 }
546 else {
547 options = __assign({}, fieldNameOrOptions);
548 // Default to objectOrReference only when fieldNameOrOptions.from is
549 // actually omitted, rather than just undefined.
550 if (!hasOwn.call(options, "from")) {
551 options.from = objectOrReference;
552 }
553 }
554 if (globalThis.__DEV__ !== false && options.from === void 0) {
555 globalThis.__DEV__ !== false && invariant.warn(7, stringifyForDisplay(Array.from(readFieldArgs)));
556 }
557 if (void 0 === options.variables) {
558 options.variables = variables;
559 }
560 return options;
561}
562function makeMergeObjectsFunction(store) {
563 return function mergeObjects(existing, incoming) {
564 if (isArray(existing) || isArray(incoming)) {
565 throw newInvariantError(8);
566 }
567 // These dynamic checks are necessary because the parameters of a
568 // custom merge function can easily have the any type, so the type
569 // system cannot always enforce the StoreObject | Reference parameter
570 // types of options.mergeObjects.
571 if (isNonNullObject(existing) && isNonNullObject(incoming)) {
572 var eType = store.getFieldValue(existing, "__typename");
573 var iType = store.getFieldValue(incoming, "__typename");
574 var typesDiffer = eType && iType && eType !== iType;
575 if (typesDiffer) {
576 return incoming;
577 }
578 if (isReference(existing) && storeValueIsStoreObject(incoming)) {
579 // Update the normalized EntityStore for the entity identified by
580 // existing.__ref, preferring/overwriting any fields contributed by the
581 // newer incoming StoreObject.
582 store.merge(existing.__ref, incoming);
583 return existing;
584 }
585 if (storeValueIsStoreObject(existing) && isReference(incoming)) {
586 // Update the normalized EntityStore for the entity identified by
587 // incoming.__ref, taking fields from the older existing object only if
588 // those fields are not already present in the newer StoreObject
589 // identified by incoming.__ref.
590 store.merge(existing, incoming.__ref);
591 return incoming;
592 }
593 if (storeValueIsStoreObject(existing) &&
594 storeValueIsStoreObject(incoming)) {
595 return __assign(__assign({}, existing), incoming);
596 }
597 }
598 return incoming;
599 };
600}
601//# sourceMappingURL=policies.js.map
\No newline at end of file