@airtable/blocks 1.10.1 → 1.10.2-experimental-640bd10-20220211

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 (74) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/dist/cjs/error_utils.js +44 -2
  3. package/dist/cjs/models/grouped_record_query_result.js +5 -14
  4. package/dist/cjs/models/linked_records_query_result.js +78 -27
  5. package/dist/cjs/models/mutations.js +18 -162
  6. package/dist/cjs/models/query_manager.js +328 -0
  7. package/dist/cjs/models/record.js +310 -55
  8. package/dist/cjs/models/record_query_result.js +4 -1
  9. package/dist/cjs/models/record_store.js +557 -765
  10. package/dist/cjs/models/table.js +6 -6
  11. package/dist/cjs/models/table_or_view_query_result.js +526 -419
  12. package/dist/cjs/models/view_data_store.js +255 -295
  13. package/dist/cjs/private_utils.js +40 -0
  14. package/dist/cjs/sdk.js +12 -2
  15. package/dist/cjs/testing/abstract_mock_airtable_interface.js +57 -11
  16. package/dist/cjs/testing/fixture_data.js +268 -0
  17. package/dist/cjs/testing/mock_base_data_stores.js +876 -0
  18. package/dist/cjs/types/airtable_interface.js +17 -2
  19. package/dist/cjs/types/block_query_spec.js +85 -0
  20. package/dist/cjs/ui/use_records.js +5 -1
  21. package/dist/cjs/unstable_testing_utils.js +55 -1
  22. package/dist/cjs/watchable.js +15 -1
  23. package/dist/types/src/error_utils.d.ts +6 -0
  24. package/dist/types/src/error_utils.d.ts.map +1 -1
  25. package/dist/types/src/models/grouped_record_query_result.d.ts +3 -3
  26. package/dist/types/src/models/grouped_record_query_result.d.ts.map +1 -1
  27. package/dist/types/src/models/linked_records_query_result.d.ts.map +1 -1
  28. package/dist/types/src/models/mutations.d.ts.map +1 -1
  29. package/dist/types/src/models/query_manager.d.ts +2 -0
  30. package/dist/types/src/models/query_manager.d.ts.map +1 -0
  31. package/dist/types/src/models/record.d.ts +12 -3
  32. package/dist/types/src/models/record.d.ts.map +1 -1
  33. package/dist/types/src/models/record_query_result.d.ts +3 -2
  34. package/dist/types/src/models/record_query_result.d.ts.map +1 -1
  35. package/dist/types/src/models/record_store.d.ts.map +1 -1
  36. package/dist/types/src/models/table_or_view_query_result.d.ts +3 -5
  37. package/dist/types/src/models/table_or_view_query_result.d.ts.map +1 -1
  38. package/dist/types/src/models/view_data_store.d.ts +0 -1
  39. package/dist/types/src/models/view_data_store.d.ts.map +1 -1
  40. package/dist/types/src/models/view_metadata_query_result.d.ts +1 -1
  41. package/dist/types/src/models/view_metadata_query_result.d.ts.map +1 -1
  42. package/dist/types/src/private_utils.d.ts +24 -1
  43. package/dist/types/src/private_utils.d.ts.map +1 -1
  44. package/dist/types/src/sdk.d.ts.map +1 -1
  45. package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts +11 -11
  46. package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts.map +1 -1
  47. package/dist/types/{test/airtable_interface_mocks → src/testing}/fixture_data.d.ts +42 -19
  48. package/dist/types/src/testing/fixture_data.d.ts.map +1 -0
  49. package/dist/types/src/testing/mock_base_data_stores.d.ts +55 -0
  50. package/dist/types/src/testing/mock_base_data_stores.d.ts.map +1 -0
  51. package/dist/types/src/types/airtable_interface.d.ts +59 -20
  52. package/dist/types/src/types/airtable_interface.d.ts.map +1 -1
  53. package/dist/types/src/types/block_query_spec.d.ts +139 -0
  54. package/dist/types/src/types/block_query_spec.d.ts.map +1 -0
  55. package/dist/types/src/types/table.d.ts +0 -2
  56. package/dist/types/src/types/table.d.ts.map +1 -1
  57. package/dist/types/src/types/view.d.ts +3 -8
  58. package/dist/types/src/types/view.d.ts.map +1 -1
  59. package/dist/types/src/ui/record_card.d.ts +1 -1
  60. package/dist/types/src/unstable_testing_utils.d.ts +4 -1
  61. package/dist/types/src/unstable_testing_utils.d.ts.map +1 -1
  62. package/dist/types/src/watchable.d.ts.map +1 -1
  63. package/dist/types/test/airtable_interface_mocks/linked_records.d.ts +1 -1
  64. package/dist/types/test/airtable_interface_mocks/linked_records.d.ts.map +1 -1
  65. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts +19 -12
  66. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts.map +1 -1
  67. package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts +1 -1
  68. package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts.map +1 -1
  69. package/dist/types/test/test_helpers.d.ts +2 -0
  70. package/dist/types/test/test_helpers.d.ts.map +1 -1
  71. package/dist/types/test/testing/fixture_data.test.d.ts +2 -0
  72. package/dist/types/test/testing/fixture_data.test.d.ts.map +1 -0
  73. package/package.json +2 -1
  74. package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts.map +0 -1
@@ -6,18 +6,26 @@ require("core-js/modules/es.symbol");
6
6
 
7
7
  require("core-js/modules/es.symbol.description");
8
8
 
9
+ require("core-js/modules/es.array.concat");
10
+
9
11
  require("core-js/modules/es.array.filter");
10
12
 
11
13
  require("core-js/modules/es.array.iterator");
12
14
 
13
15
  require("core-js/modules/es.array.map");
14
16
 
17
+ require("core-js/modules/es.object.get-own-property-descriptors");
18
+
15
19
  require("core-js/modules/es.object.to-string");
16
20
 
17
21
  require("core-js/modules/es.promise");
18
22
 
23
+ require("core-js/modules/es.set");
24
+
19
25
  require("core-js/modules/es.string.starts-with");
20
26
 
27
+ require("core-js/modules/web.dom-collections.for-each");
28
+
21
29
  require("core-js/modules/web.dom-collections.iterator");
22
30
 
23
31
  Object.defineProperty(exports, "__esModule", {
@@ -25,8 +33,6 @@ Object.defineProperty(exports, "__esModule", {
25
33
  });
26
34
  exports.default = exports.WatchableRecordStoreKeys = void 0;
27
35
 
28
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
29
-
30
36
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
31
37
 
32
38
  require("regenerator-runtime/runtime");
@@ -35,11 +41,9 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
35
41
 
36
42
  var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
37
43
 
38
- var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
39
-
40
44
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
41
45
 
42
- var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
46
+ var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
43
47
 
44
48
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
45
49
 
@@ -51,12 +55,20 @@ var _private_utils = require("../private_utils");
51
55
 
52
56
  var _error_utils = require("../error_utils");
53
57
 
58
+ var _warning = _interopRequireDefault(require("../warning"));
59
+
60
+ var _block_query_spec = require("../types/block_query_spec");
61
+
54
62
  var _abstract_model_with_async_data = _interopRequireDefault(require("./abstract_model_with_async_data"));
55
63
 
56
64
  var _record = _interopRequireDefault(require("./record"));
57
65
 
58
66
  var _view_data_store = _interopRequireDefault(require("./view_data_store"));
59
67
 
68
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
69
+
70
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
71
+
60
72
  var WatchableRecordStoreKeys = Object.freeze({
61
73
  records: 'records',
62
74
  recordIds: 'recordIds',
@@ -71,8 +83,9 @@ var WatchableCellValuesInFieldKeyPrefix = 'cellValuesInField:';
71
83
  */
72
84
 
73
85
  /**
74
- * One RecordStore exists per table, and contains all the record data associated with that table.
75
- * Table itself is for schema information only, so isn't the appropriate place for this data.
86
+ * One RecordStore exists per table, and can access *some* of the record data associated with that
87
+ * table, depending on which records are actually required for the slices of data that are subscribed.
88
+ * Table itself is for schema information only, so isn't the appropriate place for record data.
76
89
  *
77
90
  * @internal
78
91
  */
@@ -85,16 +98,6 @@ function (_AbstractModelWithAsy) {
85
98
  value: function _isWatchableKey(key) {
86
99
  return (0, _private_utils.isEnumValue)(WatchableRecordStoreKeys, key) || key.startsWith(WatchableCellValuesInFieldKeyPrefix);
87
100
  }
88
- }, {
89
- key: "_shouldLoadDataForKey",
90
- value: function _shouldLoadDataForKey(key) {
91
- // "Data" means *all* cell values in the table. If only watching records/recordIds,
92
- // we'll just load record metadata (id, createdTime, commentCount).
93
- // If only watching specific fields, we'll just load cell values in those
94
- // fields. Both of those scenarios are handled manually by this class,
95
- // instead of relying on AbstractModelWithAsyncData.
96
- return key === WatchableRecordStoreKeys.cellValues;
97
- }
98
101
  }]);
99
102
 
100
103
  function RecordStore(sdk, tableId) {
@@ -106,11 +109,15 @@ function (_AbstractModelWithAsy) {
106
109
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_recordModelsById", {});
107
110
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_primaryFieldId", void 0);
108
111
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_airtableInterface", void 0);
112
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_queryManager", void 0);
109
113
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_viewDataStoresByViewId", {});
110
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_areCellValuesLoadedByFieldId", {});
111
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_pendingCellValuesLoadPromiseByFieldId", {});
112
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_cellValuesRetainCountByFieldId", {});
114
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_airtableRecordStoreForTable", void 0);
115
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_numQueriesSubscribedToAllRecords", 0);
116
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_queryIdFromReferenceCountedLoadData", null);
117
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_loadedQuerySpecIds", new Set());
118
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_forceUnloadCallbacks", []);
113
119
  _this._airtableInterface = sdk.__airtableInterface;
120
+ _this._queryManager = sdk._queryManager;
114
121
  _this.tableId = tableId; // A bit of a hack, but we use the primary field ID to load record
115
122
  // metadata (see _getFieldIdForCausingRecordMetadataToLoad). We copy the
116
123
  // ID here instead of calling this.primaryField.id since that would crash
@@ -121,96 +128,323 @@ function (_AbstractModelWithAsy) {
121
128
  }
122
129
 
123
130
  (0, _createClass2.default)(RecordStore, [{
131
+ key: "_getRecordStoreForTable",
132
+ value: function _getRecordStoreForTable() {
133
+ if (!this._airtableRecordStoreForTable) {
134
+ var airtableRecordStoreForTable = this._airtableInterface.getTableRecordStoreIfExists(this.tableId);
135
+
136
+ (0, _error_utils.invariant)(airtableRecordStoreForTable, 'no RecordStoreForTable found for tableId %s', this.tableId);
137
+ this._airtableRecordStoreForTable = airtableRecordStoreForTable;
138
+ }
139
+
140
+ return this._airtableRecordStoreForTable;
141
+ }
142
+ }, {
124
143
  key: "getViewDataStore",
125
144
  value: function getViewDataStore(viewId) {
126
145
  if (this._viewDataStoresByViewId[viewId]) {
127
146
  return this._viewDataStoresByViewId[viewId];
128
147
  }
129
148
 
130
- (0, _error_utils.invariant)(this._data.viewsById[viewId], 'view must exist');
149
+ (0, _error_utils.invariant)(this._data.viewsById[viewId], 'view must exist'); // TODO: (#proj-blocks-sdk-record-limits) Rename ViewDataStore so that it does not
150
+ // conflict with hyperbase ViewDataStore. Here we are using the SDK ViewDataStore
151
+ // which is a thin wrapper around the hyperbase one.
152
+
131
153
  var viewDataStore = new _view_data_store.default(this._sdk, this, viewId);
132
154
  this._viewDataStoresByViewId[viewId] = viewDataStore;
133
155
  return viewDataStore;
134
156
  }
135
157
  }, {
136
- key: "watch",
137
- value: function watch(keys, callback, context) {
138
- var validKeys = (0, _get2.default)((0, _getPrototypeOf2.default)(RecordStore.prototype), "watch", this).call(this, keys, callback, context);
158
+ key: "sendViewDataDeletionIfViewIsDeleted",
159
+ value: function sendViewDataDeletionIfViewIsDeleted(viewId) {
160
+ var viewDataStoreIfExists = this._viewDataStoresByViewId[viewId];
139
161
 
140
- var fieldIdsToLoad = this._getFieldIdsToLoadFromWatchableKeys(validKeys);
162
+ if (viewDataStoreIfExists && viewDataStoreIfExists.isDeleted) {
163
+ viewDataStoreIfExists.__onDataDeletion();
141
164
 
142
- if (fieldIdsToLoad.length > 0) {
143
- (0, _private_utils.fireAndForgetPromise)(this.loadCellValuesInFieldIdsAsync.bind(this, fieldIdsToLoad));
165
+ delete this._viewDataStoresByViewId[viewId];
144
166
  }
145
-
146
- return validKeys;
147
167
  }
148
168
  }, {
149
- key: "unwatch",
150
- value: function unwatch(keys, callback, context) {
151
- var validKeys = (0, _get2.default)((0, _getPrototypeOf2.default)(RecordStore.prototype), "unwatch", this).call(this, keys, callback, context);
169
+ key: "_findMatchingBlockSubscriptionChanges",
170
+ value: function _findMatchingBlockSubscriptionChanges(changes, changeTypeToMatch) {
171
+ return changes.filter(change => change.type === changeTypeToMatch && change.tableId === this.tableId);
172
+ }
173
+ }, {
174
+ key: "_constructBlockQuerySpecAndCallbackForWatchableKeyWithRecordQueryResult",
175
+ value: function _constructBlockQuerySpecAndCallbackForWatchableKeyWithRecordQueryResult(recordQueryResult, key, callbackForRegistration, context) {
176
+ var fieldSelectionDefinition;
177
+ var originThis = recordQueryResult;
178
+ var onChangeCallback;
179
+
180
+ switch (key) {
181
+ case WatchableRecordStoreKeys.records:
182
+ case WatchableRecordStoreKeys.recordIds:
183
+ fieldSelectionDefinition = {
184
+ type: _block_query_spec.BlockFieldSelectionSpecType.SPECIFIED_FIELDS,
185
+ fieldIds: []
186
+ };
187
+
188
+ onChangeCallback = changes => {
189
+ var addedRecordsChanges = this._findMatchingBlockSubscriptionChanges(changes, _block_query_spec.BlockQuerySubscriptionChangeType.ADDED_RECORD_IDS);
190
+
191
+ var removedRecordsChanges = this._findMatchingBlockSubscriptionChanges(changes, _block_query_spec.BlockQuerySubscriptionChangeType.REMOVED_RECORD_IDS);
192
+
193
+ var addedRecordIds = [];
194
+ var removedRecordIds = [];
195
+ var _iteratorNormalCompletion = true;
196
+ var _didIteratorError = false;
197
+ var _iteratorError = undefined;
198
+
199
+ try {
200
+ for (var _iterator = addedRecordsChanges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
201
+ var addedRecordsChange = _step.value;
202
+ (0, _error_utils.invariant)(addedRecordsChange.type === _block_query_spec.BlockQuerySubscriptionChangeType.ADDED_RECORD_IDS, 'Added Records change is not a supported type');
203
+ addedRecordIds = addedRecordIds.concat(addedRecordsChange.recordIds);
204
+ }
205
+ } catch (err) {
206
+ _didIteratorError = true;
207
+ _iteratorError = err;
208
+ } finally {
209
+ try {
210
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
211
+ _iterator.return();
212
+ }
213
+ } finally {
214
+ if (_didIteratorError) {
215
+ throw _iteratorError;
216
+ }
217
+ }
218
+ }
152
219
 
153
- var fieldIdsToUnload = this._getFieldIdsToLoadFromWatchableKeys(validKeys);
220
+ var _iteratorNormalCompletion2 = true;
221
+ var _didIteratorError2 = false;
222
+ var _iteratorError2 = undefined;
154
223
 
155
- if (fieldIdsToUnload.length > 0) {
156
- this.unloadCellValuesInFieldIds(fieldIdsToUnload);
224
+ try {
225
+ for (var _iterator2 = removedRecordsChanges[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
226
+ var removedRecordsChange = _step2.value;
227
+ (0, _error_utils.invariant)(removedRecordsChange.type === _block_query_spec.BlockQuerySubscriptionChangeType.REMOVED_RECORD_IDS, 'Removed Records change is not a supported type');
228
+ removedRecordIds = removedRecordIds.concat(removedRecordsChange.recordIds);
229
+ }
230
+ } catch (err) {
231
+ _didIteratorError2 = true;
232
+ _iteratorError2 = err;
233
+ } finally {
234
+ try {
235
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
236
+ _iterator2.return();
237
+ }
238
+ } finally {
239
+ if (_didIteratorError2) {
240
+ throw _iteratorError2;
241
+ }
242
+ }
243
+ }
244
+
245
+ var recordIdsChanged = {
246
+ addedRecordIds,
247
+ removedRecordIds
248
+ };
249
+ callbackForRegistration.call(context, originThis, key, recordIdsChanged);
250
+ };
251
+
252
+ break;
253
+
254
+ case WatchableRecordStoreKeys.cellValues:
255
+ fieldSelectionDefinition = {
256
+ type: _block_query_spec.BlockFieldSelectionSpecType.ALL_FIELDS_FROM_TABLE
257
+ };
258
+
259
+ onChangeCallback = changes => {
260
+ var modifiedCellValuesChanges = this._findMatchingBlockSubscriptionChanges(changes, _block_query_spec.BlockQuerySubscriptionChangeType.MODIFIED_CELL_VALUES_FOR_TABLE);
261
+
262
+ if (modifiedCellValuesChanges.length === 0) {
263
+ callbackForRegistration.call(context, originThis, key);
264
+ return;
265
+ }
266
+
267
+ var recordsAndFieldsChanged = {
268
+ recordIds: [],
269
+ fieldIds: []
270
+ };
271
+ var _iteratorNormalCompletion3 = true;
272
+ var _didIteratorError3 = false;
273
+ var _iteratorError3 = undefined;
274
+
275
+ try {
276
+ for (var _iterator3 = modifiedCellValuesChanges[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
277
+ var modifiedCellValuesChange = _step3.value;
278
+ (0, _error_utils.invariant)(modifiedCellValuesChange.type === _block_query_spec.BlockQuerySubscriptionChangeType.MODIFIED_CELL_VALUES_FOR_TABLE, 'Modified cell value change is not a supported type');
279
+ var fieldIdsByRecordId = modifiedCellValuesChange.fieldIdsByRecordId,
280
+ fieldIds = modifiedCellValuesChange.fieldIds;
281
+ recordsAndFieldsChanged.recordIds = recordsAndFieldsChanged.recordIds.concat(Object.keys(fieldIdsByRecordId));
282
+ recordsAndFieldsChanged.fieldIds = recordsAndFieldsChanged.fieldIds.concat(fieldIds);
283
+ }
284
+ } catch (err) {
285
+ _didIteratorError3 = true;
286
+ _iteratorError3 = err;
287
+ } finally {
288
+ try {
289
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
290
+ _iterator3.return();
291
+ }
292
+ } finally {
293
+ if (_didIteratorError3) {
294
+ throw _iteratorError3;
295
+ }
296
+ }
297
+ }
298
+
299
+ callbackForRegistration.call(context, originThis, key, recordsAndFieldsChanged);
300
+ };
301
+
302
+ break;
303
+
304
+ default:
305
+ {
306
+ // Since this watch class is only called internally from within the SDK
307
+ // an error here is an internal SDK error.
308
+ (0, _error_utils.invariant)(key.startsWith(WatchableCellValuesInFieldKeyPrefix), 'Internal error - Unrecognized watch key on record_store: %s', key);
309
+ var fieldId = key.substring(WatchableCellValuesInFieldKeyPrefix.length); // Assert that fieldId is validly formatted, not that it is a valid fieldId in this table
310
+
311
+ (0, _error_utils.invariant)((0, _private_utils.isFieldId)(fieldId), 'fieldId passed as watchable fieldId is not a valid format' + fieldId);
312
+ fieldSelectionDefinition = {
313
+ type: _block_query_spec.BlockFieldSelectionSpecType.SPECIFIED_FIELDS,
314
+ fieldIds: [fieldId]
315
+ };
316
+
317
+ onChangeCallback = changes => {
318
+ var modifiedCellValuesChanges = this._findMatchingBlockSubscriptionChanges(changes, _block_query_spec.BlockQuerySubscriptionChangeType.MODIFIED_CELL_VALUES_FOR_TABLE);
319
+
320
+ if (modifiedCellValuesChanges.length === 0) {
321
+ callbackForRegistration.call(context, originThis, key);
322
+ return;
323
+ }
324
+
325
+ var recordsChanged = [];
326
+ var _iteratorNormalCompletion4 = true;
327
+ var _didIteratorError4 = false;
328
+ var _iteratorError4 = undefined;
329
+
330
+ try {
331
+ for (var _iterator4 = modifiedCellValuesChanges[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
332
+ var modifiedCellValuesChange = _step4.value;
333
+ (0, _error_utils.invariant)(modifiedCellValuesChange.type === _block_query_spec.BlockQuerySubscriptionChangeType.MODIFIED_CELL_VALUES_FOR_TABLE, 'Modified cell value change is not a supported type');
334
+ recordsChanged = recordsChanged.concat(Object.keys(modifiedCellValuesChange.fieldIdsByRecordId));
335
+ } // Why is this callback format different than when watching just cellValues?
336
+ // It's because in the past this was the format we used: https://github.com/Hyperbase/blocks-sdk/blob/32b6c59944f0d89d2c0b3b61b7db615145a8856b/packages/sdk/src/models/record_store.ts#L547-L554
337
+
338
+ } catch (err) {
339
+ _didIteratorError4 = true;
340
+ _iteratorError4 = err;
341
+ } finally {
342
+ try {
343
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
344
+ _iterator4.return();
345
+ }
346
+ } finally {
347
+ if (_didIteratorError4) {
348
+ throw _iteratorError4;
349
+ }
350
+ }
351
+ }
352
+
353
+ callbackForRegistration.call(context, originThis, key, recordsChanged, fieldId);
354
+ };
355
+
356
+ break;
357
+ }
157
358
  }
158
359
 
360
+ return {
361
+ querySpecToSubscribeWith: recordQueryResult.__constructQuerySpecForBlockFieldSelectionSpec(fieldSelectionDefinition),
362
+ onChangeCallback
363
+ };
364
+ }
365
+ }, {
366
+ key: "watch",
367
+ value: function watch(keys, callbackForRegistration, context) {
368
+ throw (0, _error_utils.spawnError)('Must not call watch on record_store directly');
369
+ }
370
+ }, {
371
+ key: "watchWithRecordQueryResult",
372
+ value: function watchWithRecordQueryResult(_ref) {
373
+ var priority = _ref.priority,
374
+ recordQueryResult = _ref.recordQueryResult,
375
+ keys = _ref.keys,
376
+ callbackForRegistration = _ref.callbackForRegistration,
377
+ context = _ref.context;
378
+
379
+ // Note that we do not call super.watch(), we use the
380
+ // alternative this._queryManager.watchWithQuerySpec
381
+ this._assertNotForceUnloaded();
382
+
383
+ var validKeys = this._getWatchableValidKeysOrThrow(keys, 'table watch');
384
+
385
+ validKeys.forEach(validKey => {
386
+ var _this$_constructBlock = this._constructBlockQuerySpecAndCallbackForWatchableKeyWithRecordQueryResult(recordQueryResult, validKey, callbackForRegistration, context),
387
+ querySpecToSubscribeWith = _this$_constructBlock.querySpecToSubscribeWith,
388
+ onChangeCallback = _this$_constructBlock.onChangeCallback;
389
+
390
+ var onChangeCallbackThatIncrementsWatchChangeCount = args => {
391
+ // Normally calling __incrementOnChangeCount is handled by queryManager.watchWithQuerySpec
392
+ // however it will only increment the change count on the recordStore. In this case we ALSO
393
+ // need to increment the change count on the recordQueryResult.
394
+ recordQueryResult.__incrementOnChangeCount();
395
+
396
+ onChangeCallback(args);
397
+ };
398
+
399
+ this._queryManager.watchWithQuerySpec(priority, querySpecToSubscribeWith, this, validKey, onChangeCallbackThatIncrementsWatchChangeCount, callbackForRegistration, context);
400
+ });
159
401
  return validKeys;
160
402
  }
161
403
  }, {
162
- key: "_getFieldIdsToLoadFromWatchableKeys",
163
- value: function _getFieldIdsToLoadFromWatchableKeys(keys) {
164
- var fieldIdsToLoad = [];
165
- var _iteratorNormalCompletion = true;
166
- var _didIteratorError = false;
167
- var _iteratorError = undefined;
404
+ key: "unwatch",
405
+ value: function unwatch(keys, callbackForRegistration, context) {
406
+ // We have already unsubscribed from all watches (because query-based watches force data to be loaded)
407
+ // so no watches are subscribed
408
+ if (this._isForceUnloaded) {
409
+ return [];
410
+ } // We warn instead of throw here because we used to warn instead of throw and don't
411
+ // want to make a breaking change.
168
412
 
169
- try {
170
- for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
171
- var key = _step.value;
172
-
173
- if (key.startsWith(WatchableCellValuesInFieldKeyPrefix)) {
174
- var fieldId = key.substring(WatchableCellValuesInFieldKeyPrefix.length);
175
- fieldIdsToLoad.push(fieldId);
176
- } else if (key === WatchableRecordStoreKeys.records || key === WatchableRecordStoreKeys.recordIds) {
177
- fieldIdsToLoad.push(this._getFieldIdForCausingRecordMetadataToLoad());
178
- }
179
- }
180
- } catch (err) {
181
- _didIteratorError = true;
182
- _iteratorError = err;
183
- } finally {
184
- try {
185
- if (!_iteratorNormalCompletion && _iterator.return != null) {
186
- _iterator.return();
187
- }
188
- } finally {
189
- if (_didIteratorError) {
190
- throw _iteratorError;
191
- }
192
- }
193
- }
194
413
 
195
- return fieldIdsToLoad;
414
+ var validKeys = this._getWatchableValidKeysOrThrow(keys, 'table unwatch', true);
415
+
416
+ validKeys.forEach(key => this._queryManager.unwatchFromQueryKey(key, callbackForRegistration, context));
417
+ return validKeys;
196
418
  }
197
419
  }, {
198
- key: "_onChangeIsDataLoaded",
199
- value: function _onChangeIsDataLoaded() {} // noop
420
+ key: "isRecordDeleted",
421
+ value: function isRecordDeleted(recordId) {
422
+ return this._getRecordStoreForTable().isRecordDeleted(recordId);
423
+ } // Maybe add a comment "pending removal of inheriting from parent class AbstractModelWithAsyncData"
424
+ // istanbul ignore next
200
425
 
426
+ }, {
427
+ key: "_onChangeIsDataLoaded",
428
+ value: function _onChangeIsDataLoaded() {
429
+ throw (0, _error_utils.spawnError)('internal error - onChangeIsDataLoaded illegal to call on record_store');
430
+ }
201
431
  /**
202
432
  * The records in this table. The order is arbitrary since records are
203
433
  * only ordered in the context of a specific view.
204
434
  */
205
435
 
436
+ }, {
437
+ key: "isRecordLoaded",
438
+ value: function isRecordLoaded(recordId) {
439
+ return this._getRecordStoreForTable().isRecordPartiallyLoaded(recordId);
440
+ }
206
441
  }, {
207
442
  key: "getRecordByIdIfExists",
208
443
  value: function getRecordByIdIfExists(recordId) {
209
- var recordsById = this._data.recordsById;
210
- (0, _error_utils.invariant)(recordsById, 'Record metadata is not loaded');
444
+ (0, _error_utils.invariant)(this._loadedQuerySpecIds.size > 0, 'Record metadata is not loaded');
211
445
  (0, _error_utils.invariant)(typeof recordId === 'string', 'getRecordById expects a string');
212
446
 
213
- if (!recordsById[recordId]) {
447
+ if (!this._getRecordStoreForTable().isRecordPartiallyLoaded(recordId)) {
214
448
  return null;
215
449
  } else {
216
450
  if (this._recordModelsById[recordId]) {
@@ -225,76 +459,64 @@ function (_AbstractModelWithAsy) {
225
459
  }, {
226
460
  key: "__onDataDeletion",
227
461
  value: function __onDataDeletion() {
228
- // also need to call unloadCellValuesInFieldIds because otherwise
229
- // on the hyperbase side, the old record store would still be subscribed
230
- // to the cell values and it will refuse a request for new subscription
231
- for (var _i = 0, _Object$keys = Object.keys(this._cellValuesRetainCountByFieldId); _i < _Object$keys.length; _i++) {
232
- var fieldId = _Object$keys[_i];
233
-
234
- while (this._cellValuesRetainCountByFieldId[fieldId] && this._cellValuesRetainCountByFieldId[fieldId] > 0) {
235
- this.unloadCellValuesInFieldIds([fieldId]);
236
- }
237
- }
238
-
239
- this._forceUnload(); // similarly unsubscribe from the view data.
240
- // this comes after _forceUnload to avoid over releasing the table data.
462
+ this._forceUnload();
241
463
 
464
+ this._queryManager.forceUnloadWatchesOnWatchableModel(this);
242
465
 
243
- var _iteratorNormalCompletion2 = true;
244
- var _didIteratorError2 = false;
245
- var _iteratorError2 = undefined;
466
+ var _iteratorNormalCompletion5 = true;
467
+ var _didIteratorError5 = false;
468
+ var _iteratorError5 = undefined;
246
469
 
247
470
  try {
248
- for (var _iterator2 = (0, _private_utils.values)(this._viewDataStoresByViewId)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
249
- var viewDataStore = _step2.value;
471
+ for (var _iterator5 = this._forceUnloadCallbacks[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
472
+ var forceUnloadCallback = _step5.value;
473
+ forceUnloadCallback();
474
+ } // similarly unsubscribe from the view data.
475
+ // this comes after _forceUnload to avoid over releasing the table data.
250
476
 
251
- viewDataStore.__onDataDeletion();
252
- }
253
477
  } catch (err) {
254
- _didIteratorError2 = true;
255
- _iteratorError2 = err;
478
+ _didIteratorError5 = true;
479
+ _iteratorError5 = err;
256
480
  } finally {
257
481
  try {
258
- if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
259
- _iterator2.return();
482
+ if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
483
+ _iterator5.return();
260
484
  }
261
485
  } finally {
262
- if (_didIteratorError2) {
263
- throw _iteratorError2;
486
+ if (_didIteratorError5) {
487
+ throw _iteratorError5;
264
488
  }
265
489
  }
266
490
  }
267
- }
268
- /**
269
- * Record metadata means record IDs, createdTime, and commentCount are loaded.
270
- * Record metadata must be loaded before creating, deleting, or updating records.
271
- */
272
491
 
273
- }, {
274
- key: "loadRecordMetadataAsync",
275
- value: function loadRecordMetadataAsync() {
276
- return _regenerator.default.async(function loadRecordMetadataAsync$(_context) {
277
- while (1) {
278
- switch (_context.prev = _context.next) {
279
- case 0:
280
- _context.next = 2;
281
- return _regenerator.default.awrap(this.loadCellValuesInFieldIdsAsync([this._getFieldIdForCausingRecordMetadataToLoad()]));
492
+ var _iteratorNormalCompletion6 = true;
493
+ var _didIteratorError6 = false;
494
+ var _iteratorError6 = undefined;
282
495
 
283
- case 2:
284
- return _context.abrupt("return", _context.sent);
496
+ try {
497
+ for (var _iterator6 = (0, _private_utils.values)(this._viewDataStoresByViewId)[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
498
+ var viewDataStore = _step6.value;
285
499
 
286
- case 3:
287
- case "end":
288
- return _context.stop();
500
+ viewDataStore.__onDataDeletion();
501
+ }
502
+ } catch (err) {
503
+ _didIteratorError6 = true;
504
+ _iteratorError6 = err;
505
+ } finally {
506
+ try {
507
+ if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
508
+ _iterator6.return();
509
+ }
510
+ } finally {
511
+ if (_didIteratorError6) {
512
+ throw _iteratorError6;
289
513
  }
290
514
  }
291
- }, null, this);
292
- }
293
- }, {
294
- key: "unloadRecordMetadata",
295
- value: function unloadRecordMetadata() {
296
- this.unloadCellValuesInFieldIds([this._getFieldIdForCausingRecordMetadataToLoad()]);
297
- }
515
+ }
516
+ } // TODO: (#proj-blocks-sdk-record-limits) Determine if we need this function,
517
+ // we shouldn't need to load the primary field in order to load metadata.
518
+ // (but may want to require it for the first version of the sdk we release)
519
+
298
520
  }, {
299
521
  key: "_getFieldIdForCausingRecordMetadataToLoad",
300
522
  value: function _getFieldIdForCausingRecordMetadataToLoad() {
@@ -305,707 +527,276 @@ function (_AbstractModelWithAsy) {
305
527
  return this._primaryFieldId;
306
528
  }
307
529
  }, {
308
- key: "areCellValuesLoadedForFieldId",
309
- value: function areCellValuesLoadedForFieldId(fieldId) {
310
- return this.isDataLoaded || this._areCellValuesLoadedByFieldId[fieldId] || false;
530
+ key: "isRecordCellValueLoadedForFieldId",
531
+ value: function isRecordCellValueLoadedForFieldId(recordId, fieldId) {
532
+ return this._getRecordStoreForTable().isRecordCellValueLoadedForFieldId(recordId, fieldId);
311
533
  }
312
534
  }, {
313
- key: "loadCellValuesInFieldIdsAsync",
314
- value: function loadCellValuesInFieldIdsAsync(fieldIds) {
315
- var fieldIdsWhichAreNotAlreadyLoadedOrLoading, pendingLoadPromises, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, _fieldId, pendingLoadPromise, loadFieldsWhichAreNotAlreadyLoadedOrLoadingPromise, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, fieldId;
316
-
317
- return _regenerator.default.async(function loadCellValuesInFieldIdsAsync$(_context2) {
318
- while (1) {
319
- switch (_context2.prev = _context2.next) {
320
- case 0:
321
- this._assertNotForceUnloaded();
322
-
323
- fieldIdsWhichAreNotAlreadyLoadedOrLoading = [];
324
- pendingLoadPromises = [];
325
- _iteratorNormalCompletion3 = true;
326
- _didIteratorError3 = false;
327
- _iteratorError3 = undefined;
328
- _context2.prev = 6;
329
-
330
- for (_iterator3 = fieldIds[Symbol.iterator](); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
331
- _fieldId = _step3.value;
332
-
333
- if (this._cellValuesRetainCountByFieldId[_fieldId] !== undefined) {
334
- this._cellValuesRetainCountByFieldId[_fieldId]++;
335
- } else {
336
- this._cellValuesRetainCountByFieldId[_fieldId] = 1;
337
- } // NOTE: we don't use this.areCellValuesLoadedForFieldId() here because
338
- // that will return true if the cell values are loaded as a result
339
- // of the entire table being loaded. In that scenario, we still
340
- // want to separately load the cell values for the field so there
341
- // is a separate subscription. Otherwise, when the table data unloads,
342
- // the field data would unload as well. This can be improved by just
343
- // subscribing to the field data without fetching it, since the cell
344
- // values are already in the block frame.
345
-
346
-
347
- if (!this._areCellValuesLoadedByFieldId[_fieldId]) {
348
- pendingLoadPromise = this._pendingCellValuesLoadPromiseByFieldId[_fieldId];
349
-
350
- if (pendingLoadPromise) {
351
- pendingLoadPromises.push(pendingLoadPromise);
352
- } else {
353
- fieldIdsWhichAreNotAlreadyLoadedOrLoading.push(_fieldId);
354
- }
355
- }
356
- }
357
-
358
- _context2.next = 14;
359
- break;
360
-
361
- case 10:
362
- _context2.prev = 10;
363
- _context2.t0 = _context2["catch"](6);
364
- _didIteratorError3 = true;
365
- _iteratorError3 = _context2.t0;
366
-
367
- case 14:
368
- _context2.prev = 14;
369
- _context2.prev = 15;
370
-
371
- if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
372
- _iterator3.return();
373
- }
374
-
375
- case 17:
376
- _context2.prev = 17;
377
-
378
- if (!_didIteratorError3) {
379
- _context2.next = 20;
380
- break;
381
- }
382
-
383
- throw _iteratorError3;
384
-
385
- case 20:
386
- return _context2.finish(17);
387
-
388
- case 21:
389
- return _context2.finish(14);
390
-
391
- case 22:
392
- if (!(fieldIdsWhichAreNotAlreadyLoadedOrLoading.length > 0)) {
393
- _context2.next = 45;
394
- break;
395
- }
396
-
397
- // Could inline _loadCellValuesInFieldIdsAsync, but following the
398
- // pattern from AbstractModelWithAsyncData where the public method
399
- // is responsible for updating retain counts and the private method
400
- // actually fetches data.
401
- loadFieldsWhichAreNotAlreadyLoadedOrLoadingPromise = this._loadCellValuesInFieldIdsAsync(fieldIdsWhichAreNotAlreadyLoadedOrLoading);
402
- pendingLoadPromises.push(loadFieldsWhichAreNotAlreadyLoadedOrLoadingPromise);
403
- _iteratorNormalCompletion4 = true;
404
- _didIteratorError4 = false;
405
- _iteratorError4 = undefined;
406
- _context2.prev = 28;
407
-
408
- for (_iterator4 = fieldIdsWhichAreNotAlreadyLoadedOrLoading[Symbol.iterator](); !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
409
- fieldId = _step4.value;
410
- this._pendingCellValuesLoadPromiseByFieldId[fieldId] = loadFieldsWhichAreNotAlreadyLoadedOrLoadingPromise;
411
- } // Doing `.then` instead of performing these actions directly in
412
- // _loadCellValuesInFieldIdsAsync so this is similar to
413
- // AbstractModelWithAsyncData. The idea is to refactor to avoid code
414
- // duplication, so keeping them similar for now hopefully will make the
415
- // refactor simpler.
416
-
417
-
418
- _context2.next = 36;
419
- break;
420
-
421
- case 32:
422
- _context2.prev = 32;
423
- _context2.t1 = _context2["catch"](28);
424
- _didIteratorError4 = true;
425
- _iteratorError4 = _context2.t1;
426
-
427
- case 36:
428
- _context2.prev = 36;
429
- _context2.prev = 37;
430
-
431
- if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
432
- _iterator4.return();
433
- }
434
-
435
- case 39:
436
- _context2.prev = 39;
437
-
438
- if (!_didIteratorError4) {
439
- _context2.next = 42;
440
- break;
441
- }
442
-
443
- throw _iteratorError4;
444
-
445
- case 42:
446
- return _context2.finish(39);
447
-
448
- case 43:
449
- return _context2.finish(36);
450
-
451
- case 44:
452
- loadFieldsWhichAreNotAlreadyLoadedOrLoadingPromise.then(changedKeys => {
453
- var _iteratorNormalCompletion5 = true;
454
- var _didIteratorError5 = false;
455
- var _iteratorError5 = undefined;
456
-
457
- try {
458
- for (var _iterator5 = fieldIdsWhichAreNotAlreadyLoadedOrLoading[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
459
- var fieldId = _step5.value;
460
- this._areCellValuesLoadedByFieldId[fieldId] = true;
461
- this._pendingCellValuesLoadPromiseByFieldId[fieldId] = undefined;
462
- }
463
- } catch (err) {
464
- _didIteratorError5 = true;
465
- _iteratorError5 = err;
466
- } finally {
467
- try {
468
- if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
469
- _iterator5.return();
470
- }
471
- } finally {
472
- if (_didIteratorError5) {
473
- throw _iteratorError5;
474
- }
475
- }
476
- }
477
-
478
- var _iteratorNormalCompletion6 = true;
479
- var _didIteratorError6 = false;
480
- var _iteratorError6 = undefined;
481
-
482
- try {
483
- for (var _iterator6 = changedKeys[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
484
- var key = _step6.value;
485
-
486
- this._onChange(key);
487
- }
488
- } catch (err) {
489
- _didIteratorError6 = true;
490
- _iteratorError6 = err;
491
- } finally {
492
- try {
493
- if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
494
- _iterator6.return();
495
- }
496
- } finally {
497
- if (_didIteratorError6) {
498
- throw _iteratorError6;
499
- }
500
- }
501
- }
502
- });
503
-
504
- case 45:
505
- _context2.next = 47;
506
- return _regenerator.default.awrap(Promise.all(pendingLoadPromises));
507
-
508
- case 47:
509
- case "end":
510
- return _context2.stop();
511
- }
512
- }
513
- }, null, this, [[6, 10, 14, 22], [15,, 17, 21], [28, 32, 36, 44], [37,, 39, 43]]);
535
+ key: "getRecordCellValueByFieldId",
536
+ value: function getRecordCellValueByFieldId(recordId, fieldId) {
537
+ return this._getRecordStoreForTable().getRecordCellValueByFieldId(recordId, fieldId);
514
538
  }
515
539
  }, {
516
- key: "_loadCellValuesInFieldIdsAsync",
517
- value: function _loadCellValuesInFieldIdsAsync(fieldIds) {
518
- var _ref, newRecordsById, existingRecordsById, _iteratorNormalCompletion7, _didIteratorError7, _iteratorError7, _iterator7, _step7, _step7$value, recordId, newRecordObj, existingRecordObj, existingCellValuesByFieldId, i, fieldId, changedKeys;
519
-
520
- return _regenerator.default.async(function _loadCellValuesInFieldIdsAsync$(_context3) {
540
+ key: "getRecordCommentCount",
541
+ value: function getRecordCommentCount(recordId) {
542
+ return this._getRecordStoreForTable().getRecordCommentCount(recordId);
543
+ }
544
+ }, {
545
+ key: "getRecordCreatedTime",
546
+ value: function getRecordCreatedTime(recordId) {
547
+ return this._getRecordStoreForTable().getRecordCreatedTime(recordId);
548
+ }
549
+ }, {
550
+ key: "_loadCellValuesForQueryAsync",
551
+ value: function _loadCellValuesForQueryAsync(query) {
552
+ var querySpecIdPromise, onForceUnload, querySpecId;
553
+ return _regenerator.default.async(function _loadCellValuesForQueryAsync$(_context2) {
521
554
  while (1) {
522
- switch (_context3.prev = _context3.next) {
555
+ switch (_context2.prev = _context2.next) {
523
556
  case 0:
524
- _context3.next = 2;
525
- return _regenerator.default.awrap(this._airtableInterface.fetchAndSubscribeToCellValuesInFieldsAsync(this.tableId, fieldIds));
526
-
527
- case 2:
528
- _ref = _context3.sent;
529
- newRecordsById = _ref.recordsById;
530
-
531
- // Merge with existing data.
532
- if (!this._data.recordsById) {
533
- this._data.recordsById = {};
534
- }
535
-
536
- existingRecordsById = this._data.recordsById;
537
- _iteratorNormalCompletion7 = true;
538
- _didIteratorError7 = false;
539
- _iteratorError7 = undefined;
540
- _context3.prev = 9;
541
-
542
- for (_iterator7 = (0, _private_utils.entries)((0, _private_utils.cast)(newRecordsById))[Symbol.iterator](); !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
543
- _step7$value = (0, _slicedToArray2.default)(_step7.value, 2), recordId = _step7$value[0], newRecordObj = _step7$value[1];
544
-
545
- if (!(0, _private_utils.has)(existingRecordsById, recordId)) {
546
- existingRecordsById[recordId] = newRecordObj;
547
- } else {
548
- existingRecordObj = existingRecordsById[recordId]; // Metadata (createdTime, commentCount) should already be up to date,
549
- // but just verify for sanity. If this doesn't catch anything, can
550
- // remove it for perf.
551
-
552
- (0, _error_utils.invariant)(existingRecordObj.commentCount === newRecordObj.commentCount, 'comment count out of sync');
553
- (0, _error_utils.invariant)(existingRecordObj.createdTime === newRecordObj.createdTime, 'created time out of sync');
554
-
555
- if (!existingRecordObj.cellValuesByFieldId) {
556
- existingRecordObj.cellValuesByFieldId = {};
557
- }
558
-
559
- existingCellValuesByFieldId = existingRecordObj.cellValuesByFieldId;
560
-
561
- for (i = 0; i < fieldIds.length; i++) {
562
- fieldId = fieldIds[i];
563
- existingCellValuesByFieldId[fieldId] = newRecordObj.cellValuesByFieldId ? newRecordObj.cellValuesByFieldId[fieldId] : undefined;
557
+ this._assertNotForceUnloaded(); // We send all queries through query manager. PublicAirtableInterface does
558
+ // all reference counting for queries, and doesn't send cell data over the bridge
559
+ // if it's already being tracked in the PublicRecordStore.
560
+
561
+
562
+ querySpecIdPromise = this._sdk._queryManager.fetchAndSubscribeToQueryAsync(_objectSpread({}, query, {
563
+ sourceTableId: this.tableId
564
+ }));
565
+
566
+ onForceUnload = () => {
567
+ var querySpecId;
568
+ return _regenerator.default.async(function _callee$(_context) {
569
+ while (1) {
570
+ switch (_context.prev = _context.next) {
571
+ case 0:
572
+ _context.next = 2;
573
+ return _regenerator.default.awrap(querySpecIdPromise);
574
+
575
+ case 2:
576
+ querySpecId = _context.sent;
577
+
578
+ if (this._loadedQuerySpecIds.has(querySpecId)) {
579
+ this._unloadCellValuesForQueryIdsIgnoringForceUnloadedness([querySpecId]);
580
+ }
581
+
582
+ case 4:
583
+ case "end":
584
+ return _context.stop();
585
+ }
564
586
  }
565
- }
566
- }
567
-
568
- _context3.next = 17;
569
- break;
570
-
571
- case 13:
572
- _context3.prev = 13;
573
- _context3.t0 = _context3["catch"](9);
574
- _didIteratorError7 = true;
575
- _iteratorError7 = _context3.t0;
576
-
577
- case 17:
578
- _context3.prev = 17;
579
- _context3.prev = 18;
580
-
581
- if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
582
- _iterator7.return();
583
- }
584
-
585
- case 20:
586
- _context3.prev = 20;
587
-
588
- if (!_didIteratorError7) {
589
- _context3.next = 23;
590
- break;
591
- }
592
-
593
- throw _iteratorError7;
587
+ }, null, this);
588
+ };
594
589
 
595
- case 23:
596
- return _context3.finish(20);
590
+ this._forceUnloadCallbacks.push(onForceUnload);
597
591
 
598
- case 24:
599
- return _context3.finish(17);
592
+ _context2.next = 6;
593
+ return _regenerator.default.awrap(querySpecIdPromise);
600
594
 
601
- case 25:
602
- changedKeys = fieldIds.map(fieldId => WatchableCellValuesInFieldKeyPrefix + fieldId); // Need to trigger onChange for records and recordIds since watching either
603
- // of those causes record metadata to be loaded (via _getFieldIdForCausingRecordMetadataToLoad)
604
- // and by convention we trigger a change event when data loads.
595
+ case 6:
596
+ querySpecId = _context2.sent;
605
597
 
606
- changedKeys.push(WatchableRecordStoreKeys.records);
607
- changedKeys.push(WatchableRecordStoreKeys.recordIds); // Also trigger cellValues changes since the cell values in the fields
608
- // are now loaded.
598
+ this._loadedQuerySpecIds.add(querySpecId);
609
599
 
610
- changedKeys.push(WatchableRecordStoreKeys.cellValues);
611
- return _context3.abrupt("return", changedKeys);
600
+ return _context2.abrupt("return", querySpecId);
612
601
 
613
- case 30:
602
+ case 9:
614
603
  case "end":
615
- return _context3.stop();
604
+ return _context2.stop();
616
605
  }
617
606
  }
618
- }, null, this, [[9, 13, 17, 25], [18,, 20, 24]]);
607
+ }, null, this);
619
608
  }
620
609
  }, {
621
- key: "unloadCellValuesInFieldIds",
622
- value: function unloadCellValuesInFieldIds(fieldIds) {
610
+ key: "_unloadCellValuesForQueryIds",
611
+ value: function _unloadCellValuesForQueryIds(queryIds) {
623
612
  if (this._isForceUnloaded) {
624
613
  return;
625
614
  }
626
615
 
627
- var fieldIdsWithZeroRetainCount = [];
628
- var _iteratorNormalCompletion8 = true;
629
- var _didIteratorError8 = false;
630
- var _iteratorError8 = undefined;
631
-
632
- try {
633
- for (var _iterator8 = fieldIds[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
634
- var fieldId = _step8.value;
635
- var fieldRetainCount = this._cellValuesRetainCountByFieldId[fieldId] || 0;
636
- fieldRetainCount--;
616
+ this._unloadCellValuesForQueryIdsIgnoringForceUnloadedness(queryIds);
617
+ }
618
+ }, {
619
+ key: "_unloadCellValuesForQueryIdsIgnoringForceUnloadedness",
620
+ value: function _unloadCellValuesForQueryIdsIgnoringForceUnloadedness(queryIds) {
621
+ this._queryManager.unsubscribeFromQueryIds(queryIds);
637
622
 
638
- if (fieldRetainCount < 0) {
639
- console.log('Field data over-released'); // eslint-disable-line no-console
623
+ var _iteratorNormalCompletion7 = true;
624
+ var _didIteratorError7 = false;
625
+ var _iteratorError7 = undefined;
640
626
 
641
- fieldRetainCount = 0;
642
- }
627
+ try {
628
+ for (var _iterator7 = queryIds[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
629
+ var queryId = _step7.value;
643
630
 
644
- this._cellValuesRetainCountByFieldId[fieldId] = fieldRetainCount;
631
+ var queryIdWasLoaded = this._loadedQuerySpecIds.delete(queryId);
645
632
 
646
- if (fieldRetainCount === 0) {
647
- fieldIdsWithZeroRetainCount.push(fieldId);
633
+ if (!queryIdWasLoaded) {
634
+ (0, _warning.default)('Over unsubscribed from record store');
648
635
  }
649
636
  }
650
637
  } catch (err) {
651
- _didIteratorError8 = true;
652
- _iteratorError8 = err;
638
+ _didIteratorError7 = true;
639
+ _iteratorError7 = err;
653
640
  } finally {
654
641
  try {
655
- if (!_iteratorNormalCompletion8 && _iterator8.return != null) {
656
- _iterator8.return();
642
+ if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
643
+ _iterator7.return();
657
644
  }
658
645
  } finally {
659
- if (_didIteratorError8) {
660
- throw _iteratorError8;
646
+ if (_didIteratorError7) {
647
+ throw _iteratorError7;
661
648
  }
662
649
  }
663
650
  }
664
-
665
- if (fieldIdsWithZeroRetainCount.length > 0) {
666
- // Don't unload immediately. Wait a while in case something else
667
- // requests the data, so we can avoid going back to liveapp or
668
- // the network.
669
- setTimeout(() => {
670
- // Make sure the retain count is still zero, since it may
671
- // have been incremented before the timeout fired.
672
- var fieldIdsToUnload = fieldIdsWithZeroRetainCount.filter(fieldId => {
673
- return this._cellValuesRetainCountByFieldId[fieldId] === 0;
674
- });
675
-
676
- if (fieldIdsToUnload.length > 0) {
677
- // Set _areCellValuesLoadedByFieldId to false before calling _unloadCellValuesInFieldIds
678
- // since _unloadCellValuesInFieldIds will check if *any* fields are still loaded.
679
- var _iteratorNormalCompletion9 = true;
680
- var _didIteratorError9 = false;
681
- var _iteratorError9 = undefined;
682
-
683
- try {
684
- for (var _iterator9 = fieldIdsToUnload[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
685
- var fieldId = _step9.value;
686
- this._areCellValuesLoadedByFieldId[fieldId] = false;
687
- }
688
- } catch (err) {
689
- _didIteratorError9 = true;
690
- _iteratorError9 = err;
691
- } finally {
692
- try {
693
- if (!_iteratorNormalCompletion9 && _iterator9.return != null) {
694
- _iterator9.return();
695
- }
696
- } finally {
697
- if (_didIteratorError9) {
698
- throw _iteratorError9;
651
+ }
652
+ }, {
653
+ key: "loadViewDataStoreAndCellValuesForFieldIdsAsync",
654
+ value: function loadViewDataStoreAndCellValuesForFieldIdsAsync(viewId, fieldIdsToLoadOrNullIfAllFields) {
655
+ var fieldSelection;
656
+ return _regenerator.default.async(function loadViewDataStoreAndCellValuesForFieldIdsAsync$(_context3) {
657
+ while (1) {
658
+ switch (_context3.prev = _context3.next) {
659
+ case 0:
660
+ // We do not need to initialize a ViewDataStore, as it's a thin wrapper around the
661
+ // hyperbase viewMetadataStore which can be initialized after a query inflates the data.
662
+ // A complicating factor is what happens if (this) recordStore or viewDataStore are
663
+ // forceUnload'ed. It is fine to track the query in only record store because:
664
+ // - If either is force unloaded without the other the query must be kept active
665
+ // - If a recordStore is force unloaded the children viewDataStores are also unloaded
666
+ // because the table has been deleted. Therefore we can track it in only record_store.
667
+ fieldSelection = fieldIdsToLoadOrNullIfAllFields ? {
668
+ type: _block_query_spec.BlockFieldSelectionSpecType.SPECIFIED_FIELDS,
669
+ fieldIds: fieldIdsToLoadOrNullIfAllFields
670
+ } : {
671
+ type: _block_query_spec.BlockFieldSelectionSpecType.ALL_FIELDS_FROM_TABLE
672
+ }; // By issuing this query we both populate cell values requested AND view metadata
673
+ // Cell values requested will be accessible inside record_store
674
+
675
+ _context3.next = 3;
676
+ return _regenerator.default.awrap(this._loadCellValuesForQueryAsync({
677
+ sourceType: _block_query_spec.BlockQuerySourceType.VIEW,
678
+ sourceViewId: viewId,
679
+ recordSelection: {
680
+ fieldSelection
681
+ },
682
+ viewMetadataSelection: {
683
+ shouldIncludeVisibleRecordIds: true,
684
+ shouldIncludeFieldOrder: true,
685
+ shouldIncludeGroups: true,
686
+ shouldIncludeGroupingLevels: true,
687
+ shouldIncludeColorsForRecordId: true
699
688
  }
700
- }
701
- }
689
+ }));
702
690
 
703
- this._unloadCellValuesInFieldIds(fieldIdsToUnload);
691
+ case 3:
692
+ return _context3.abrupt("return", _context3.sent);
693
+
694
+ case 4:
695
+ case "end":
696
+ return _context3.stop();
704
697
  }
705
- }, _abstract_model_with_async_data.default.__DATA_UNLOAD_DELAY_MS);
706
- }
698
+ }
699
+ }, null, this);
707
700
  }
708
701
  }, {
709
- key: "_unloadCellValuesInFieldIds",
710
- value: function _unloadCellValuesInFieldIds(fieldIds) {
711
- this._airtableInterface.unsubscribeFromCellValuesInFields(this.tableId, fieldIds);
712
-
713
- this._afterUnloadDataOrUnloadCellValuesInFieldIds(fieldIds);
702
+ key: "unloadViewDataStoreAndCellValuesWithQueryIds",
703
+ value: function unloadViewDataStoreAndCellValuesWithQueryIds(queryIds) {
704
+ // Note that we do not update _numQueriesSubscribedToAllRecords since this query
705
+ // does not subscribe to all cells in a table.
706
+ this._unloadCellValuesForQueryIds(queryIds);
714
707
  }
715
708
  }, {
716
- key: "_loadDataAsync",
717
- value: function _loadDataAsync() {
718
- var tableData, changedKeys, _iteratorNormalCompletion10, _didIteratorError10, _iteratorError10, _iterator10, _step10, fieldId;
719
-
720
- return _regenerator.default.async(function _loadDataAsync$(_context4) {
709
+ key: "loadAllCellValuesInFieldIdsAsync",
710
+ value: function loadAllCellValuesInFieldIdsAsync(fieldIds) {
711
+ var queryId;
712
+ return _regenerator.default.async(function loadAllCellValuesInFieldIdsAsync$(_context4) {
721
713
  while (1) {
722
714
  switch (_context4.prev = _context4.next) {
723
715
  case 0:
724
716
  _context4.next = 2;
725
- return _regenerator.default.awrap(this._airtableInterface.fetchAndSubscribeToTableDataAsync(this.tableId));
717
+ return _regenerator.default.awrap(this._loadCellValuesForQueryAsync({
718
+ sourceType: _block_query_spec.BlockQuerySourceType.TABLE,
719
+ recordSelection: {
720
+ fieldSelection: {
721
+ type: _block_query_spec.BlockFieldSelectionSpecType.SPECIFIED_FIELDS,
722
+ fieldIds
723
+ }
724
+ }
725
+ }));
726
726
 
727
727
  case 2:
728
- tableData = _context4.sent;
729
- this._data.recordsById = tableData.recordsById;
730
- changedKeys = [WatchableRecordStoreKeys.records, WatchableRecordStoreKeys.recordIds, WatchableRecordStoreKeys.cellValues];
731
- _iteratorNormalCompletion10 = true;
732
- _didIteratorError10 = false;
733
- _iteratorError10 = undefined;
734
- _context4.prev = 8;
735
-
736
- for (_iterator10 = (0, _private_utils.keys)(this._data.fieldsById)[Symbol.iterator](); !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
737
- fieldId = _step10.value;
738
- changedKeys.push(WatchableCellValuesInFieldKeyPrefix + fieldId);
739
- }
728
+ queryId = _context4.sent;
729
+ this._numQueriesSubscribedToAllRecords += 1;
730
+ return _context4.abrupt("return", queryId);
740
731
 
741
- _context4.next = 16;
742
- break;
743
-
744
- case 12:
745
- _context4.prev = 12;
746
- _context4.t0 = _context4["catch"](8);
747
- _didIteratorError10 = true;
748
- _iteratorError10 = _context4.t0;
749
-
750
- case 16:
751
- _context4.prev = 16;
752
- _context4.prev = 17;
753
-
754
- if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
755
- _iterator10.return();
756
- }
757
-
758
- case 19:
759
- _context4.prev = 19;
760
-
761
- if (!_didIteratorError10) {
762
- _context4.next = 22;
763
- break;
764
- }
765
-
766
- throw _iteratorError10;
767
-
768
- case 22:
769
- return _context4.finish(19);
770
-
771
- case 23:
772
- return _context4.finish(16);
773
-
774
- case 24:
775
- return _context4.abrupt("return", changedKeys);
776
-
777
- case 25:
732
+ case 5:
778
733
  case "end":
779
734
  return _context4.stop();
780
735
  }
781
736
  }
782
- }, null, this, [[8, 12, 16, 24], [17,, 19, 23]]);
783
- }
784
- }, {
785
- key: "_unloadData",
786
- value: function _unloadData() {
787
- this._airtableInterface.unsubscribeFromTableData(this.tableId);
788
-
789
- this._afterUnloadDataOrUnloadCellValuesInFieldIds();
737
+ }, null, this);
790
738
  }
791
739
  }, {
792
- key: "_afterUnloadDataOrUnloadCellValuesInFieldIds",
793
- value: function _afterUnloadDataOrUnloadCellValuesInFieldIds(unloadedFieldIds) {
794
- var areAnyFieldsLoaded = this.isDataLoaded || (0, _private_utils.values)(this._areCellValuesLoadedByFieldId).some(isLoaded => isLoaded);
795
-
796
- if (!this.isDeleted) {
797
- if (!areAnyFieldsLoaded) {
798
- this._data.recordsById = undefined;
799
- } else if (!this.isDataLoaded) {
800
- var fieldIdsToClear;
801
-
802
- if (unloadedFieldIds) {
803
- // Specific fields were unloaded, so clear out the cell values for those fields.
804
- fieldIdsToClear = unloadedFieldIds;
805
- } else {
806
- // The entire table was unloaded, but some individual fields are still loaded.
807
- // We need to clear out the cell values of every field that was unloaded.
808
- // This is kind of slow, but hopefully uncommon.
809
- var fieldIds = Object.keys(this._data.fieldsById);
810
- fieldIdsToClear = fieldIds.filter(fieldId => !this._areCellValuesLoadedByFieldId[fieldId]);
811
- }
812
-
813
- var recordsById = this._data.recordsById;
814
- var _iteratorNormalCompletion11 = true;
815
- var _didIteratorError11 = false;
816
- var _iteratorError11 = undefined;
817
-
818
- try {
819
- for (var _iterator11 = (0, _private_utils.values)(recordsById || {})[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
820
- var recordObj = _step11.value;
740
+ key: "loadAllCellValuesAsync",
741
+ value: function loadAllCellValuesAsync() {
742
+ var queryId;
743
+ return _regenerator.default.async(function loadAllCellValuesAsync$(_context5) {
744
+ while (1) {
745
+ switch (_context5.prev = _context5.next) {
746
+ case 0:
747
+ _context5.next = 2;
748
+ return _regenerator.default.awrap(this._loadCellValuesForQueryAsync({
749
+ sourceType: _block_query_spec.BlockQuerySourceType.TABLE,
750
+ recordSelection: {
751
+ fieldSelection: {
752
+ type: _block_query_spec.BlockFieldSelectionSpecType.ALL_FIELDS_FROM_TABLE
753
+ }
754
+ }
755
+ }));
821
756
 
822
- for (var i = 0; i < fieldIdsToClear.length; i++) {
823
- var fieldId = fieldIdsToClear[i];
757
+ case 2:
758
+ queryId = _context5.sent;
759
+ this._numQueriesSubscribedToAllRecords += 1;
760
+ return _context5.abrupt("return", queryId);
824
761
 
825
- if (recordObj.cellValuesByFieldId) {
826
- recordObj.cellValuesByFieldId[fieldId] = undefined;
827
- }
828
- }
829
- }
830
- } catch (err) {
831
- _didIteratorError11 = true;
832
- _iteratorError11 = err;
833
- } finally {
834
- try {
835
- if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
836
- _iterator11.return();
837
- }
838
- } finally {
839
- if (_didIteratorError11) {
840
- throw _iteratorError11;
841
- }
842
- }
762
+ case 5:
763
+ case "end":
764
+ return _context5.stop();
843
765
  }
844
766
  }
845
- }
846
-
847
- if (!areAnyFieldsLoaded) {
848
- this._recordModelsById = {};
849
- }
767
+ }, null, this);
850
768
  }
851
769
  }, {
852
- key: "triggerOnChangeForDirtyPaths",
853
- value: function triggerOnChangeForDirtyPaths(dirtyPaths) {
854
- if (this.isRecordMetadataLoaded && dirtyPaths.recordsById) {
855
- // Since tables don't have a record order, need to detect if a record
856
- // was created or deleted and trigger onChange for records.
857
- var dirtyFieldIdsSet = {};
858
- var addedRecordIds = [];
859
- var removedRecordIds = [];
860
- var _iteratorNormalCompletion12 = true;
861
- var _didIteratorError12 = false;
862
- var _iteratorError12 = undefined;
863
-
864
- try {
865
- for (var _iterator12 = (0, _private_utils.entries)(dirtyPaths.recordsById)[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
866
- var _step12$value = (0, _slicedToArray2.default)(_step12.value, 2),
867
- recordId = _step12$value[0],
868
- dirtyRecordPaths = _step12$value[1];
869
-
870
- if (dirtyRecordPaths && dirtyRecordPaths._isDirty) {
871
- // If the entire record is dirty, it was either created or deleted.
872
- (0, _error_utils.invariant)(this._data.recordsById, 'No recordsById');
873
-
874
- if ((0, _private_utils.has)(this._data.recordsById, recordId)) {
875
- addedRecordIds.push(recordId);
876
- } else {
877
- removedRecordIds.push(recordId);
878
- var recordModel = this._recordModelsById[recordId];
879
-
880
- if (recordModel) {
881
- // Remove the Record model if it was deleted.
882
- delete this._recordModelsById[recordId];
883
- }
884
- }
885
- } else {
886
- var _recordModel = this._recordModelsById[recordId];
887
-
888
- if (_recordModel) {
889
- _recordModel.__triggerOnChangeForDirtyPaths(dirtyRecordPaths);
890
- }
891
- }
892
-
893
- var cellValuesByFieldId = dirtyRecordPaths.cellValuesByFieldId;
894
-
895
- if (cellValuesByFieldId) {
896
- for (var _i2 = 0, _Object$keys2 = Object.keys(cellValuesByFieldId); _i2 < _Object$keys2.length; _i2++) {
897
- var fieldId = _Object$keys2[_i2];
898
- dirtyFieldIdsSet[fieldId] = true;
899
- }
900
- }
901
- } // Now that we've composed our created/deleted record ids arrays, let's fire
902
- // the records onChange event if any records were created or deleted.
903
-
904
- } catch (err) {
905
- _didIteratorError12 = true;
906
- _iteratorError12 = err;
907
- } finally {
908
- try {
909
- if (!_iteratorNormalCompletion12 && _iterator12.return != null) {
910
- _iterator12.return();
911
- }
912
- } finally {
913
- if (_didIteratorError12) {
914
- throw _iteratorError12;
915
- }
916
- }
917
- }
918
-
919
- if (addedRecordIds.length > 0 || removedRecordIds.length > 0) {
920
- this._onChange(WatchableRecordStoreKeys.records, {
921
- addedRecordIds,
922
- removedRecordIds
923
- });
924
-
925
- this._onChange(WatchableRecordStoreKeys.recordIds, {
926
- addedRecordIds,
927
- removedRecordIds
928
- });
929
- } // NOTE: this is an experimental (and somewhat messy) way to watch
930
- // for changes to cells in a table, as an alternative to implementing
931
- // full event bubbling. For now, it unblocks the things we want to
932
- // build, but we may replace it.
933
- // If we keep it, could be more efficient by not calling _onChange
934
- // if there are no subscribers.
935
- // TODO: don't trigger changes for fields that aren't supposed to be loaded
936
- // (in some cases, e.g. record created, liveapp will send cell values
937
- // that we're not subscribed to).
938
-
939
-
940
- var fieldIds = Object.freeze(Object.keys(dirtyFieldIdsSet));
941
- var recordIds = Object.freeze(Object.keys(dirtyPaths.recordsById));
942
-
943
- if (fieldIds.length > 0 && recordIds.length > 0) {
944
- this._onChange(WatchableRecordStoreKeys.cellValues, {
945
- recordIds,
946
- fieldIds
947
- });
948
- }
770
+ key: "unloadCellValuesForQueryIdsThatAreSubscribedToAllCells",
771
+ value: function unloadCellValuesForQueryIdsThatAreSubscribedToAllCells(queryIds) {
772
+ this._unloadCellValuesForQueryIds(queryIds);
949
773
 
950
- var _iteratorNormalCompletion13 = true;
951
- var _didIteratorError13 = false;
952
- var _iteratorError13 = undefined;
774
+ this._numQueriesSubscribedToAllRecords -= queryIds.length;
775
+ } // Maybe add a comment "pending removal of inheriting from parent class AbstractModelWithAsyncData"
776
+ // istanbul ignore next
953
777
 
954
- try {
955
- for (var _iterator13 = fieldIds[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
956
- var _fieldId2 = _step13.value;
778
+ }, {
779
+ key: "_loadDataAsync",
780
+ value: function _loadDataAsync() {
781
+ return _regenerator.default.async(function _loadDataAsync$(_context6) {
782
+ while (1) {
783
+ switch (_context6.prev = _context6.next) {
784
+ case 0:
785
+ throw (0, _error_utils.spawnError)('Internal error - SDK called loadData on record_store');
957
786
 
958
- this._onChange(WatchableCellValuesInFieldKeyPrefix + _fieldId2, recordIds, _fieldId2);
959
- }
960
- } catch (err) {
961
- _didIteratorError13 = true;
962
- _iteratorError13 = err;
963
- } finally {
964
- try {
965
- if (!_iteratorNormalCompletion13 && _iterator13.return != null) {
966
- _iterator13.return();
967
- }
968
- } finally {
969
- if (_didIteratorError13) {
970
- throw _iteratorError13;
971
- }
787
+ case 1:
788
+ case "end":
789
+ return _context6.stop();
972
790
  }
973
791
  }
974
- }
975
-
976
- if (dirtyPaths.viewOrder) {
977
- // clean up deleted views
978
- var _iteratorNormalCompletion14 = true;
979
- var _didIteratorError14 = false;
980
- var _iteratorError14 = undefined;
981
-
982
- try {
983
- for (var _iterator14 = (0, _private_utils.entries)(this._viewDataStoresByViewId)[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
984
- var _step14$value = (0, _slicedToArray2.default)(_step14.value, 2),
985
- viewId = _step14$value[0],
986
- viewDataStore = _step14$value[1];
987
-
988
- if (viewDataStore.isDeleted) {
989
- viewDataStore.__onDataDeletion();
792
+ });
793
+ } // Maybe add a comment "pending removal of inheriting from parent class AbstractModelWithAsyncData"
794
+ // istanbul ignore next
990
795
 
991
- delete this._viewDataStoresByViewId[viewId];
992
- }
993
- }
994
- } catch (err) {
995
- _didIteratorError14 = true;
996
- _iteratorError14 = err;
997
- } finally {
998
- try {
999
- if (!_iteratorNormalCompletion14 && _iterator14.return != null) {
1000
- _iterator14.return();
1001
- }
1002
- } finally {
1003
- if (_didIteratorError14) {
1004
- throw _iteratorError14;
1005
- }
1006
- }
1007
- }
1008
- }
796
+ }, {
797
+ key: "_unloadData",
798
+ value: function _unloadData() {
799
+ throw (0, _error_utils.spawnError)('Internal error - SDK called unloadData on record_store');
1009
800
  }
1010
801
  }, {
1011
802
  key: "_dataOrNullIfDeleted",
@@ -1017,9 +808,7 @@ function (_AbstractModelWithAsy) {
1017
808
  }, {
1018
809
  key: "records",
1019
810
  get: function get() {
1020
- var recordsById = this._data.recordsById;
1021
- (0, _error_utils.invariant)(recordsById, 'Record metadata is not loaded');
1022
- var records = Object.keys(recordsById).map(recordId => {
811
+ var records = this.recordIds.map(recordId => {
1023
812
  var record = this.getRecordByIdIfExists(recordId);
1024
813
  (0, _error_utils.invariant)(record, 'record');
1025
814
  return record;
@@ -1034,14 +823,17 @@ function (_AbstractModelWithAsy) {
1034
823
  }, {
1035
824
  key: "recordIds",
1036
825
  get: function get() {
1037
- var recordsById = this._data.recordsById;
1038
- (0, _error_utils.invariant)(recordsById, 'Record metadata is not loaded');
1039
- return Object.keys(recordsById);
826
+ (0, _error_utils.invariant)(this.isSubscribedToAllRecordsInTable, 'Record metadata is not loaded for all records in table');
827
+
828
+ var recordIds = this._getRecordStoreForTable().getPartiallyLoadedRecordIds();
829
+
830
+ (0, _error_utils.invariant)(recordIds, 'Record metadata is not loaded');
831
+ return recordIds;
1040
832
  }
1041
833
  }, {
1042
- key: "isRecordMetadataLoaded",
834
+ key: "isSubscribedToAllRecordsInTable",
1043
835
  get: function get() {
1044
- return !!this._data.recordsById;
836
+ return this._numQueriesSubscribedToAllRecords > 0;
1045
837
  }
1046
838
  }]);
1047
839
  return RecordStore;