houdini 0.13.7-alpha.1 → 0.13.7

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/build/cmd.js CHANGED
File without changes
@@ -7,7 +7,7 @@ import { InMemorySubscriptions } from './subscription';
7
7
  export declare class Cache {
8
8
  _internal_unstable: CacheInternal;
9
9
  constructor(config: Config);
10
- write({ layer: layerID, ...args }: {
10
+ write({ layer: layerID, notifySubscribers, ...args }: {
11
11
  data: {
12
12
  [key: string]: GraphQLValue;
13
13
  };
@@ -16,7 +16,9 @@ export declare class Cache {
16
16
  parent?: string;
17
17
  layer?: LayerID | null;
18
18
  applyUpdates?: boolean;
19
- }): LayerID;
19
+ notifySubscribers?: SubscriptionSpec[];
20
+ forceNotify?: boolean;
21
+ }): SubscriptionSpec[];
20
22
  read(...args: Parameters<CacheInternal['getSelection']>): {
21
23
  data: GraphQLObject | null;
22
24
  partial: boolean;
@@ -42,7 +44,7 @@ declare class CacheInternal {
42
44
  cache: Cache;
43
45
  lifetimes: GarbageCollector;
44
46
  });
45
- writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, }: {
47
+ writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, forceNotify, }: {
46
48
  data: {
47
49
  [key: string]: GraphQLValue;
48
50
  };
@@ -55,6 +57,7 @@ declare class CacheInternal {
55
57
  layer: Layer;
56
58
  toNotify?: SubscriptionSpec[];
57
59
  applyUpdates?: boolean;
60
+ forceNotify?: boolean;
58
61
  }): SubscriptionSpec[];
59
62
  getSelection({ selection, parent, variables, }: {
60
63
  selection: SubscriptionSelection;
@@ -82,7 +85,7 @@ declare class CacheInternal {
82
85
  partial: boolean;
83
86
  hasData: boolean;
84
87
  };
85
- extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, }: {
88
+ extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, forceNotify, }: {
86
89
  value: GraphQLValue[];
87
90
  recordID: string;
88
91
  key: string;
@@ -94,6 +97,7 @@ declare class CacheInternal {
94
97
  fields: SubscriptionSelection;
95
98
  layer: Layer;
96
99
  startingWith: number;
100
+ forceNotify?: boolean;
97
101
  }): {
98
102
  nestedIDs: LinkedList;
99
103
  newIDs: (string | null)[];
@@ -75,7 +75,7 @@ var Cache = /** @class */ (function () {
75
75
  Cache.prototype.write = function (_a) {
76
76
  var e_1, _b;
77
77
  var _c;
78
- var layerID = _a.layer, args = __rest(_a, ["layer"]);
78
+ var layerID = _a.layer, _d = _a.notifySubscribers, notifySubscribers = _d === void 0 ? [] : _d, args = __rest(_a, ["layer", "notifySubscribers"]);
79
79
  // find the correct layer
80
80
  var layer = layerID
81
81
  ? this._internal_unstable.storage.getLayer(layerID)
@@ -86,8 +86,8 @@ var Cache = /** @class */ (function () {
86
86
  // function's identity
87
87
  var notified = [];
88
88
  try {
89
- for (var subscribers_1 = __values(subscribers), subscribers_1_1 = subscribers_1.next(); !subscribers_1_1.done; subscribers_1_1 = subscribers_1.next()) {
90
- var spec = subscribers_1_1.value;
89
+ for (var _e = __values(subscribers.concat(notifySubscribers)), _f = _e.next(); !_f.done; _f = _e.next()) {
90
+ var spec = _f.value;
91
91
  // if we haven't added the set yet
92
92
  if (!notified.includes(spec.set)) {
93
93
  notified.push(spec.set);
@@ -103,12 +103,12 @@ var Cache = /** @class */ (function () {
103
103
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
104
104
  finally {
105
105
  try {
106
- if (subscribers_1_1 && !subscribers_1_1.done && (_b = subscribers_1.return)) _b.call(subscribers_1);
106
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
107
107
  }
108
108
  finally { if (e_1) throw e_1.error; }
109
109
  }
110
110
  // return the id to the caller so they can resolve the layer if it was optimistic
111
- return layer.id;
111
+ return subscribers;
112
112
  };
113
113
  // reconstruct an object with the fields/relations specified by a selection
114
114
  Cache.prototype.read = function () {
@@ -187,7 +187,7 @@ var CacheInternal = /** @class */ (function () {
187
187
  var e_2, _b;
188
188
  var _this = this;
189
189
  var _c;
190
- var data = _a.data, selection = _a.selection, _d = _a.variables, variables = _d === void 0 ? {} : _d, _e = _a.root, root = _e === void 0 ? exports.rootID : _e, _f = _a.parent, parent = _f === void 0 ? exports.rootID : _f, _g = _a.applyUpdates, applyUpdates = _g === void 0 ? false : _g, layer = _a.layer, _h = _a.toNotify, toNotify = _h === void 0 ? [] : _h;
190
+ var data = _a.data, selection = _a.selection, _d = _a.variables, variables = _d === void 0 ? {} : _d, _e = _a.root, root = _e === void 0 ? exports.rootID : _e, _f = _a.parent, parent = _f === void 0 ? exports.rootID : _f, _g = _a.applyUpdates, applyUpdates = _g === void 0 ? false : _g, layer = _a.layer, _h = _a.toNotify, toNotify = _h === void 0 ? [] : _h, forceNotify = _a.forceNotify;
191
191
  // if the cache is disabled, dont do anything
192
192
  if (this._disabled) {
193
193
  return [];
@@ -212,12 +212,12 @@ var CacheInternal = /** @class */ (function () {
212
212
  // if the layer we are updating is the top most layer for the field
213
213
  // then its value is "live". It is providing the current value and
214
214
  // subscribers need to know if the value changed
215
- var displayLayer = displayLayers.length === 0 || displayLayers.includes(layer.id);
215
+ var displayLayer = layer.isDisplayLayer(displayLayers);
216
216
  // if we are writing to the display layer we need to refresh the lifetime of the value
217
217
  if (displayLayer) {
218
218
  this_1.lifetimes.resetLifetime(parent, key);
219
219
  }
220
- // any non-scalar is defined as a field with no selection
220
+ // any scalar is defined as a field with no selection
221
221
  if (!fields) {
222
222
  // the value to write to the layer
223
223
  var newValue = value;
@@ -234,7 +234,7 @@ var CacheInternal = /** @class */ (function () {
234
234
  }
235
235
  // if the value changed on a layer that impacts the current latest value
236
236
  var valueChanged = JSON.stringify(newValue) !== JSON.stringify(previousValue);
237
- if (valueChanged && displayLayer) {
237
+ if (displayLayer && (valueChanged || forceNotify)) {
238
238
  // we need to add the fields' subscribers to the set of callbacks
239
239
  // we need to invoke
240
240
  toNotify.push.apply(toNotify, __spread(currentSubcribers));
@@ -290,7 +290,7 @@ var CacheInternal = /** @class */ (function () {
290
290
  // write the link to the layer
291
291
  layer.writeLink(parent, key, linkedID);
292
292
  // if the link target of this field changed and it was responsible for the current subscription
293
- if (linkedID && displayLayer && linkChange) {
293
+ if (linkedID && displayLayer && (linkChange || forceNotify)) {
294
294
  // we need to clear the subscriptions in the previous link
295
295
  // and add them to the new link
296
296
  if (previousValue && typeof previousValue === 'string') {
@@ -317,6 +317,7 @@ var CacheInternal = /** @class */ (function () {
317
317
  toNotify: toNotify,
318
318
  applyUpdates: applyUpdates,
319
319
  layer: layer,
320
+ forceNotify: true,
320
321
  });
321
322
  }
322
323
  }
@@ -373,6 +374,7 @@ var CacheInternal = /** @class */ (function () {
373
374
  fields: fields,
374
375
  layer: layer,
375
376
  startingWith: applyUpdates && update === 'append' ? oldIDs_2.length : 0,
377
+ forceNotify: forceNotify,
376
378
  }), newIDs = _j.newIDs, nestedIDs = _j.nestedIDs;
377
379
  // if we're supposed to apply this write as an update, we need to figure out how
378
380
  if (applyUpdates && update) {
@@ -447,7 +449,7 @@ var CacheInternal = /** @class */ (function () {
447
449
  // is still valid would not be triggered
448
450
  var contentChanged = JSON.stringify(linkedIDs) !== JSON.stringify(oldIDs_2);
449
451
  // we need to look at the last time we saw each subscriber to check if they need to be added to the spec
450
- if (contentChanged) {
452
+ if (contentChanged || forceNotify) {
451
453
  toNotify.push.apply(toNotify, __spread(currentSubcribers));
452
454
  }
453
455
  try {
@@ -777,7 +779,7 @@ var CacheInternal = /** @class */ (function () {
777
779
  CacheInternal.prototype.extractNestedListIDs = function (_a) {
778
780
  var e_11, _b;
779
781
  var _c;
780
- var value = _a.value, abstract = _a.abstract, recordID = _a.recordID, key = _a.key, linkedType = _a.linkedType, fields = _a.fields, variables = _a.variables, applyUpdates = _a.applyUpdates, specs = _a.specs, layer = _a.layer, startingWith = _a.startingWith;
782
+ var value = _a.value, abstract = _a.abstract, recordID = _a.recordID, key = _a.key, linkedType = _a.linkedType, fields = _a.fields, variables = _a.variables, applyUpdates = _a.applyUpdates, specs = _a.specs, layer = _a.layer, startingWith = _a.startingWith, forceNotify = _a.forceNotify;
781
783
  // build up the two lists
782
784
  var nestedIDs = [];
783
785
  var newIDs = [];
@@ -798,6 +800,7 @@ var CacheInternal = /** @class */ (function () {
798
800
  specs: specs,
799
801
  layer: layer,
800
802
  startingWith: startingWith,
803
+ forceNotify: forceNotify,
801
804
  });
802
805
  // add the list of new ids to our list
803
806
  newIDs.push.apply(newIDs, __spread(inner.newIDs));
@@ -849,6 +852,7 @@ var CacheInternal = /** @class */ (function () {
849
852
  toNotify: specs,
850
853
  applyUpdates: applyUpdates,
851
854
  layer: layer,
855
+ forceNotify: forceNotify,
852
856
  });
853
857
  newIDs.push(linkedID);
854
858
  nestedIDs[i] = linkedID;
@@ -32,6 +32,7 @@ export declare class Layer {
32
32
  getOperations(id: string, field: string): Operation[] | undefined;
33
33
  writeField(id: string, field: string, value: GraphQLField): LayerID;
34
34
  writeLink(id: string, field: string, value: null | string | LinkedList): LayerID;
35
+ isDisplayLayer(displayLayers: number[]): boolean;
35
36
  clear(): void;
36
37
  applyDeletes(): void;
37
38
  delete(id: string): void;
@@ -243,6 +243,7 @@ var InMemoryStorage = /** @class */ (function () {
243
243
  var layer = this.data[layerIndex++];
244
244
  // if the layer is optimistic, we can't go further
245
245
  if (layer.optimistic) {
246
+ layerIndex--;
246
247
  break;
247
248
  }
248
249
  // apply the layer onto our base
@@ -351,7 +352,14 @@ var Layer = /** @class */ (function () {
351
352
  this.links[id] = __assign(__assign({}, this.links[id]), (_b = {}, _b[field] = value, _b));
352
353
  return this.id;
353
354
  };
355
+ Layer.prototype.isDisplayLayer = function (displayLayers) {
356
+ return (displayLayers.length === 0 ||
357
+ displayLayers.includes(this.id) ||
358
+ Math.max.apply(Math, __spread(displayLayers)) < this.id);
359
+ };
354
360
  Layer.prototype.clear = function () {
361
+ // before we clear the data of the layer, look for any subscribers that need to be updated
362
+ // now that everything has been notified we can reset the data
355
363
  this.links = {};
356
364
  this.fields = {};
357
365
  this.operations = {};
@@ -63,15 +63,15 @@ function mutation(document) {
63
63
  var sessionStore = adapter_mjs_1.getSession();
64
64
  // return an async function that sends the mutation go the server
65
65
  return function (variables, mutationConfig) { return __awaiter(_this, void 0, void 0, function () {
66
- var optimisticResponse, layer, result, error_1;
66
+ var layer, optimisticResponse, toNotify, result, error_1;
67
67
  return __generator(this, function (_a) {
68
68
  switch (_a.label) {
69
69
  case 0:
70
- optimisticResponse = mutationConfig === null || mutationConfig === void 0 ? void 0 : mutationConfig.optimisticResponse;
71
70
  layer = cache_1.default._internal_unstable.storage.createLayer(true);
72
- // if there is an optimistic response then we need to write the value immediately
71
+ optimisticResponse = mutationConfig === null || mutationConfig === void 0 ? void 0 : mutationConfig.optimisticResponse;
72
+ toNotify = [];
73
73
  if (optimisticResponse) {
74
- cache_1.default.write({
74
+ toNotify = cache_1.default.write({
75
75
  selection: artifact.selection,
76
76
  // make sure that any scalar values get processed into something we can cache
77
77
  data: scalars_1.marshalSelection({
@@ -102,8 +102,14 @@ function mutation(document) {
102
102
  selection: artifact.selection,
103
103
  data: result.data,
104
104
  variables: variables,
105
- // if we had an optimistic response we need to write to the appropriate layer
105
+ // write to the mutation's layer
106
106
  layer: layer.id,
107
+ // notify any subscribers that we updated with the optimistic response
108
+ // in order to address situations where the optimistic update was wrong
109
+ notifySubscribers: toNotify,
110
+ // make sure that we notify subscribers for any values that we overwrite
111
+ // in order to address any race conditions when comparing the previous value
112
+ forceNotify: true,
107
113
  });
108
114
  // merge the layer back into the cache
109
115
  cache_1.default._internal_unstable.storage.resolveLayer(layer.id);
@@ -7,7 +7,7 @@ import { InMemorySubscriptions } from './subscription';
7
7
  export declare class Cache {
8
8
  _internal_unstable: CacheInternal;
9
9
  constructor(config: Config);
10
- write({ layer: layerID, ...args }: {
10
+ write({ layer: layerID, notifySubscribers, ...args }: {
11
11
  data: {
12
12
  [key: string]: GraphQLValue;
13
13
  };
@@ -16,7 +16,9 @@ export declare class Cache {
16
16
  parent?: string;
17
17
  layer?: LayerID | null;
18
18
  applyUpdates?: boolean;
19
- }): LayerID;
19
+ notifySubscribers?: SubscriptionSpec[];
20
+ forceNotify?: boolean;
21
+ }): SubscriptionSpec[];
20
22
  read(...args: Parameters<CacheInternal['getSelection']>): {
21
23
  data: GraphQLObject | null;
22
24
  partial: boolean;
@@ -42,7 +44,7 @@ declare class CacheInternal {
42
44
  cache: Cache;
43
45
  lifetimes: GarbageCollector;
44
46
  });
45
- writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, }: {
47
+ writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, forceNotify, }: {
46
48
  data: {
47
49
  [key: string]: GraphQLValue;
48
50
  };
@@ -55,6 +57,7 @@ declare class CacheInternal {
55
57
  layer: Layer;
56
58
  toNotify?: SubscriptionSpec[];
57
59
  applyUpdates?: boolean;
60
+ forceNotify?: boolean;
58
61
  }): SubscriptionSpec[];
59
62
  getSelection({ selection, parent, variables, }: {
60
63
  selection: SubscriptionSelection;
@@ -82,7 +85,7 @@ declare class CacheInternal {
82
85
  partial: boolean;
83
86
  hasData: boolean;
84
87
  };
85
- extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, }: {
88
+ extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, forceNotify, }: {
86
89
  value: GraphQLValue[];
87
90
  recordID: string;
88
91
  key: string;
@@ -94,6 +97,7 @@ declare class CacheInternal {
94
97
  fields: SubscriptionSelection;
95
98
  layer: Layer;
96
99
  startingWith: number;
100
+ forceNotify?: boolean;
97
101
  }): {
98
102
  nestedIDs: LinkedList;
99
103
  newIDs: (string | null)[];
@@ -75,7 +75,7 @@ var Cache = /** @class */ (function () {
75
75
  Cache.prototype.write = function (_a) {
76
76
  var e_1, _b;
77
77
  var _c;
78
- var layerID = _a.layer, args = __rest(_a, ["layer"]);
78
+ var layerID = _a.layer, _d = _a.notifySubscribers, notifySubscribers = _d === void 0 ? [] : _d, args = __rest(_a, ["layer", "notifySubscribers"]);
79
79
  // find the correct layer
80
80
  var layer = layerID
81
81
  ? this._internal_unstable.storage.getLayer(layerID)
@@ -86,8 +86,8 @@ var Cache = /** @class */ (function () {
86
86
  // function's identity
87
87
  var notified = [];
88
88
  try {
89
- for (var subscribers_1 = __values(subscribers), subscribers_1_1 = subscribers_1.next(); !subscribers_1_1.done; subscribers_1_1 = subscribers_1.next()) {
90
- var spec = subscribers_1_1.value;
89
+ for (var _e = __values(subscribers.concat(notifySubscribers)), _f = _e.next(); !_f.done; _f = _e.next()) {
90
+ var spec = _f.value;
91
91
  // if we haven't added the set yet
92
92
  if (!notified.includes(spec.set)) {
93
93
  notified.push(spec.set);
@@ -103,12 +103,12 @@ var Cache = /** @class */ (function () {
103
103
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
104
104
  finally {
105
105
  try {
106
- if (subscribers_1_1 && !subscribers_1_1.done && (_b = subscribers_1.return)) _b.call(subscribers_1);
106
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
107
107
  }
108
108
  finally { if (e_1) throw e_1.error; }
109
109
  }
110
110
  // return the id to the caller so they can resolve the layer if it was optimistic
111
- return layer.id;
111
+ return subscribers;
112
112
  };
113
113
  // reconstruct an object with the fields/relations specified by a selection
114
114
  Cache.prototype.read = function () {
@@ -187,7 +187,7 @@ var CacheInternal = /** @class */ (function () {
187
187
  var e_2, _b;
188
188
  var _this = this;
189
189
  var _c;
190
- var data = _a.data, selection = _a.selection, _d = _a.variables, variables = _d === void 0 ? {} : _d, _e = _a.root, root = _e === void 0 ? exports.rootID : _e, _f = _a.parent, parent = _f === void 0 ? exports.rootID : _f, _g = _a.applyUpdates, applyUpdates = _g === void 0 ? false : _g, layer = _a.layer, _h = _a.toNotify, toNotify = _h === void 0 ? [] : _h;
190
+ var data = _a.data, selection = _a.selection, _d = _a.variables, variables = _d === void 0 ? {} : _d, _e = _a.root, root = _e === void 0 ? exports.rootID : _e, _f = _a.parent, parent = _f === void 0 ? exports.rootID : _f, _g = _a.applyUpdates, applyUpdates = _g === void 0 ? false : _g, layer = _a.layer, _h = _a.toNotify, toNotify = _h === void 0 ? [] : _h, forceNotify = _a.forceNotify;
191
191
  // if the cache is disabled, dont do anything
192
192
  if (this._disabled) {
193
193
  return [];
@@ -212,12 +212,12 @@ var CacheInternal = /** @class */ (function () {
212
212
  // if the layer we are updating is the top most layer for the field
213
213
  // then its value is "live". It is providing the current value and
214
214
  // subscribers need to know if the value changed
215
- var displayLayer = displayLayers.length === 0 || displayLayers.includes(layer.id);
215
+ var displayLayer = layer.isDisplayLayer(displayLayers);
216
216
  // if we are writing to the display layer we need to refresh the lifetime of the value
217
217
  if (displayLayer) {
218
218
  this_1.lifetimes.resetLifetime(parent, key);
219
219
  }
220
- // any non-scalar is defined as a field with no selection
220
+ // any scalar is defined as a field with no selection
221
221
  if (!fields) {
222
222
  // the value to write to the layer
223
223
  var newValue = value;
@@ -234,7 +234,7 @@ var CacheInternal = /** @class */ (function () {
234
234
  }
235
235
  // if the value changed on a layer that impacts the current latest value
236
236
  var valueChanged = JSON.stringify(newValue) !== JSON.stringify(previousValue);
237
- if (valueChanged && displayLayer) {
237
+ if (displayLayer && (valueChanged || forceNotify)) {
238
238
  // we need to add the fields' subscribers to the set of callbacks
239
239
  // we need to invoke
240
240
  toNotify.push.apply(toNotify, __spread(currentSubcribers));
@@ -290,7 +290,7 @@ var CacheInternal = /** @class */ (function () {
290
290
  // write the link to the layer
291
291
  layer.writeLink(parent, key, linkedID);
292
292
  // if the link target of this field changed and it was responsible for the current subscription
293
- if (linkedID && displayLayer && linkChange) {
293
+ if (linkedID && displayLayer && (linkChange || forceNotify)) {
294
294
  // we need to clear the subscriptions in the previous link
295
295
  // and add them to the new link
296
296
  if (previousValue && typeof previousValue === 'string') {
@@ -317,6 +317,7 @@ var CacheInternal = /** @class */ (function () {
317
317
  toNotify: toNotify,
318
318
  applyUpdates: applyUpdates,
319
319
  layer: layer,
320
+ forceNotify: true,
320
321
  });
321
322
  }
322
323
  }
@@ -373,6 +374,7 @@ var CacheInternal = /** @class */ (function () {
373
374
  fields: fields,
374
375
  layer: layer,
375
376
  startingWith: applyUpdates && update === 'append' ? oldIDs_2.length : 0,
377
+ forceNotify: forceNotify,
376
378
  }), newIDs = _j.newIDs, nestedIDs = _j.nestedIDs;
377
379
  // if we're supposed to apply this write as an update, we need to figure out how
378
380
  if (applyUpdates && update) {
@@ -447,7 +449,7 @@ var CacheInternal = /** @class */ (function () {
447
449
  // is still valid would not be triggered
448
450
  var contentChanged = JSON.stringify(linkedIDs) !== JSON.stringify(oldIDs_2);
449
451
  // we need to look at the last time we saw each subscriber to check if they need to be added to the spec
450
- if (contentChanged) {
452
+ if (contentChanged || forceNotify) {
451
453
  toNotify.push.apply(toNotify, __spread(currentSubcribers));
452
454
  }
453
455
  try {
@@ -777,7 +779,7 @@ var CacheInternal = /** @class */ (function () {
777
779
  CacheInternal.prototype.extractNestedListIDs = function (_a) {
778
780
  var e_11, _b;
779
781
  var _c;
780
- var value = _a.value, abstract = _a.abstract, recordID = _a.recordID, key = _a.key, linkedType = _a.linkedType, fields = _a.fields, variables = _a.variables, applyUpdates = _a.applyUpdates, specs = _a.specs, layer = _a.layer, startingWith = _a.startingWith;
782
+ var value = _a.value, abstract = _a.abstract, recordID = _a.recordID, key = _a.key, linkedType = _a.linkedType, fields = _a.fields, variables = _a.variables, applyUpdates = _a.applyUpdates, specs = _a.specs, layer = _a.layer, startingWith = _a.startingWith, forceNotify = _a.forceNotify;
781
783
  // build up the two lists
782
784
  var nestedIDs = [];
783
785
  var newIDs = [];
@@ -798,6 +800,7 @@ var CacheInternal = /** @class */ (function () {
798
800
  specs: specs,
799
801
  layer: layer,
800
802
  startingWith: startingWith,
803
+ forceNotify: forceNotify,
801
804
  });
802
805
  // add the list of new ids to our list
803
806
  newIDs.push.apply(newIDs, __spread(inner.newIDs));
@@ -849,6 +852,7 @@ var CacheInternal = /** @class */ (function () {
849
852
  toNotify: specs,
850
853
  applyUpdates: applyUpdates,
851
854
  layer: layer,
855
+ forceNotify: forceNotify,
852
856
  });
853
857
  newIDs.push(linkedID);
854
858
  nestedIDs[i] = linkedID;
@@ -32,6 +32,7 @@ export declare class Layer {
32
32
  getOperations(id: string, field: string): Operation[] | undefined;
33
33
  writeField(id: string, field: string, value: GraphQLField): LayerID;
34
34
  writeLink(id: string, field: string, value: null | string | LinkedList): LayerID;
35
+ isDisplayLayer(displayLayers: number[]): boolean;
35
36
  clear(): void;
36
37
  applyDeletes(): void;
37
38
  delete(id: string): void;
@@ -243,6 +243,7 @@ var InMemoryStorage = /** @class */ (function () {
243
243
  var layer = this.data[layerIndex++];
244
244
  // if the layer is optimistic, we can't go further
245
245
  if (layer.optimistic) {
246
+ layerIndex--;
246
247
  break;
247
248
  }
248
249
  // apply the layer onto our base
@@ -351,7 +352,14 @@ var Layer = /** @class */ (function () {
351
352
  this.links[id] = __assign(__assign({}, this.links[id]), (_b = {}, _b[field] = value, _b));
352
353
  return this.id;
353
354
  };
355
+ Layer.prototype.isDisplayLayer = function (displayLayers) {
356
+ return (displayLayers.length === 0 ||
357
+ displayLayers.includes(this.id) ||
358
+ Math.max.apply(Math, __spread(displayLayers)) < this.id);
359
+ };
354
360
  Layer.prototype.clear = function () {
361
+ // before we clear the data of the layer, look for any subscribers that need to be updated
362
+ // now that everything has been notified we can reset the data
355
363
  this.links = {};
356
364
  this.fields = {};
357
365
  this.operations = {};
@@ -63,15 +63,15 @@ function mutation(document) {
63
63
  var sessionStore = adapter_mjs_1.getSession();
64
64
  // return an async function that sends the mutation go the server
65
65
  return function (variables, mutationConfig) { return __awaiter(_this, void 0, void 0, function () {
66
- var optimisticResponse, layer, result, error_1;
66
+ var layer, optimisticResponse, toNotify, result, error_1;
67
67
  return __generator(this, function (_a) {
68
68
  switch (_a.label) {
69
69
  case 0:
70
- optimisticResponse = mutationConfig === null || mutationConfig === void 0 ? void 0 : mutationConfig.optimisticResponse;
71
70
  layer = cache_1.default._internal_unstable.storage.createLayer(true);
72
- // if there is an optimistic response then we need to write the value immediately
71
+ optimisticResponse = mutationConfig === null || mutationConfig === void 0 ? void 0 : mutationConfig.optimisticResponse;
72
+ toNotify = [];
73
73
  if (optimisticResponse) {
74
- cache_1.default.write({
74
+ toNotify = cache_1.default.write({
75
75
  selection: artifact.selection,
76
76
  // make sure that any scalar values get processed into something we can cache
77
77
  data: scalars_1.marshalSelection({
@@ -102,8 +102,14 @@ function mutation(document) {
102
102
  selection: artifact.selection,
103
103
  data: result.data,
104
104
  variables: variables,
105
- // if we had an optimistic response we need to write to the appropriate layer
105
+ // write to the mutation's layer
106
106
  layer: layer.id,
107
+ // notify any subscribers that we updated with the optimistic response
108
+ // in order to address situations where the optimistic update was wrong
109
+ notifySubscribers: toNotify,
110
+ // make sure that we notify subscribers for any values that we overwrite
111
+ // in order to address any race conditions when comparing the previous value
112
+ forceNotify: true,
107
113
  });
108
114
  // merge the layer back into the cache
109
115
  cache_1.default._internal_unstable.storage.resolveLayer(layer.id);
@@ -7,7 +7,7 @@ import { InMemorySubscriptions } from './subscription';
7
7
  export declare class Cache {
8
8
  _internal_unstable: CacheInternal;
9
9
  constructor(config: Config);
10
- write({ layer: layerID, ...args }: {
10
+ write({ layer: layerID, notifySubscribers, ...args }: {
11
11
  data: {
12
12
  [key: string]: GraphQLValue;
13
13
  };
@@ -16,7 +16,9 @@ export declare class Cache {
16
16
  parent?: string;
17
17
  layer?: LayerID | null;
18
18
  applyUpdates?: boolean;
19
- }): LayerID;
19
+ notifySubscribers?: SubscriptionSpec[];
20
+ forceNotify?: boolean;
21
+ }): SubscriptionSpec[];
20
22
  read(...args: Parameters<CacheInternal['getSelection']>): {
21
23
  data: GraphQLObject;
22
24
  partial: boolean;
@@ -42,7 +44,7 @@ declare class CacheInternal {
42
44
  cache: Cache;
43
45
  lifetimes: GarbageCollector;
44
46
  });
45
- writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, }: {
47
+ writeSelection({ data, selection, variables, root, parent, applyUpdates, layer, toNotify, forceNotify, }: {
46
48
  data: {
47
49
  [key: string]: GraphQLValue;
48
50
  };
@@ -55,6 +57,7 @@ declare class CacheInternal {
55
57
  layer: Layer;
56
58
  toNotify?: SubscriptionSpec[];
57
59
  applyUpdates?: boolean;
60
+ forceNotify?: boolean;
58
61
  }): SubscriptionSpec[];
59
62
  getSelection({ selection, parent, variables, }: {
60
63
  selection: SubscriptionSelection;
@@ -82,7 +85,7 @@ declare class CacheInternal {
82
85
  partial: boolean;
83
86
  hasData: boolean;
84
87
  };
85
- extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, }: {
88
+ extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, startingWith, forceNotify, }: {
86
89
  value: GraphQLValue[];
87
90
  recordID: string;
88
91
  key: string;
@@ -94,6 +97,7 @@ declare class CacheInternal {
94
97
  fields: SubscriptionSelection;
95
98
  layer: Layer;
96
99
  startingWith: number;
100
+ forceNotify?: boolean;
97
101
  }): {
98
102
  nestedIDs: LinkedList;
99
103
  newIDs: (string | null)[];