@airtable/blocks 1.9.0-experimental-5565d56-20211029 → 1.10.1

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 (61) hide show
  1. package/CHANGELOG.md +15 -4
  2. package/dist/cjs/error_utils.js +0 -17
  3. package/dist/cjs/models/grouped_record_query_result.js +14 -5
  4. package/dist/cjs/models/linked_records_query_result.js +27 -75
  5. package/dist/cjs/models/mutations.js +162 -18
  6. package/dist/cjs/models/record.js +56 -309
  7. package/dist/cjs/models/record_query_result.js +1 -4
  8. package/dist/cjs/models/record_store.js +765 -554
  9. package/dist/cjs/models/table.js +7 -7
  10. package/dist/cjs/models/table_or_view_query_result.js +414 -480
  11. package/dist/cjs/models/view.js +1 -1
  12. package/dist/cjs/models/view_data_store.js +295 -243
  13. package/dist/cjs/private_utils.js +0 -40
  14. package/dist/cjs/sdk.js +2 -12
  15. package/dist/cjs/testing/abstract_mock_airtable_interface.js +10 -55
  16. package/dist/cjs/ui/use_records.js +1 -5
  17. package/dist/cjs/watchable.js +1 -15
  18. package/dist/types/src/models/grouped_record_query_result.d.ts +3 -3
  19. package/dist/types/src/models/grouped_record_query_result.d.ts.map +1 -1
  20. package/dist/types/src/models/linked_records_query_result.d.ts.map +1 -1
  21. package/dist/types/src/models/mutations.d.ts.map +1 -1
  22. package/dist/types/src/models/record.d.ts +4 -13
  23. package/dist/types/src/models/record.d.ts.map +1 -1
  24. package/dist/types/src/models/record_query_result.d.ts +2 -3
  25. package/dist/types/src/models/record_query_result.d.ts.map +1 -1
  26. package/dist/types/src/models/record_store.d.ts.map +1 -1
  27. package/dist/types/src/models/table.d.ts +1 -1
  28. package/dist/types/src/models/table_or_view_query_result.d.ts +5 -3
  29. package/dist/types/src/models/table_or_view_query_result.d.ts.map +1 -1
  30. package/dist/types/src/models/view.d.ts +1 -1
  31. package/dist/types/src/models/view_data_store.d.ts +1 -0
  32. package/dist/types/src/models/view_data_store.d.ts.map +1 -1
  33. package/dist/types/src/models/view_metadata_query_result.d.ts +1 -1
  34. package/dist/types/src/models/view_metadata_query_result.d.ts.map +1 -1
  35. package/dist/types/src/private_utils.d.ts +3 -26
  36. package/dist/types/src/private_utils.d.ts.map +1 -1
  37. package/dist/types/src/sdk.d.ts.map +1 -1
  38. package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts +11 -11
  39. package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts.map +1 -1
  40. package/dist/types/src/types/airtable_interface.d.ts +19 -43
  41. package/dist/types/src/types/airtable_interface.d.ts.map +1 -1
  42. package/dist/types/src/types/table.d.ts +2 -0
  43. package/dist/types/src/types/table.d.ts.map +1 -1
  44. package/dist/types/src/types/view.d.ts +8 -3
  45. package/dist/types/src/types/view.d.ts.map +1 -1
  46. package/dist/types/src/watchable.d.ts.map +1 -1
  47. package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts +5 -7
  48. package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts.map +1 -1
  49. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts +11 -18
  50. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts.map +1 -1
  51. package/dist/types/test/test_helpers.d.ts +0 -2
  52. package/dist/types/test/test_helpers.d.ts.map +1 -1
  53. package/package.json +2 -3
  54. package/dist/cjs/models/query_manager.js +0 -327
  55. package/dist/cjs/types/block_query_spec.js +0 -85
  56. package/dist/types/src/models/query_manager.d.ts +0 -2
  57. package/dist/types/src/models/query_manager.d.ts.map +0 -1
  58. package/dist/types/src/types/block_query_spec.d.ts +0 -139
  59. package/dist/types/src/types/block_query_spec.d.ts.map +0 -1
  60. package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts +0 -51
  61. package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -9,13 +9,24 @@ Not every commit needs to result in a change to this file (e.g. docs and chore c
9
9
  commit that affects the code in a way that consumers might care about should include edits to the
10
10
  'Unreleased' section though. Breaking changes should be prefixed with `**BREAKING:**`.
11
11
 
12
- ## [Unreleased](https://github.com/airtable/blocks/compare/@airtable/blocks@1.9.0...HEAD)
12
+ ## [Unreleased](https://github.com/airtable/blocks/compare/@airtable/blocks@1.10.1...HEAD)
13
13
 
14
- <<<<<<< seankeenan-at-fixTypoAndFormattingFromOpenPR
14
+ No changes.
15
+
16
+ ## [1.10.1](https://github.com/airtable/blocks/compare/@airtable/blocks@1.10.0...@airtable/blocks@1.10.1) - 2021-12-22
17
+
18
+ - Update examples for table, view and field URLs.
19
+ - Use `keyof any` instead of `PropertyKey` in type definition to avoid incompatibility with the
20
+ "[keyofStringsOnly](https://www.typescriptlang.org/tsconfig#keyofStringsOnly)" tsconfig option
21
+
22
+ ## [1.10.0](https://github.com/airtable/blocks/compare/@airtable/blocks@1.9.0...@airtable/blocks@1.10.0) - 2021-11-03
15
23
 
16
- - # Fix typo in cursor.ts documentation - thanks @m2creates!
24
+ - Fix typo in cursor.ts documentation - thanks @m2creates!
17
25
  - Add new `calendarDay` icon (and micro variant)
18
- > > > > > > > main
26
+ - Update documentation to include attachment url guidance
27
+ - Update field metadata writes documentation to mention that `null` will be coerced to `''`
28
+ - Fix a bug when unloading data from a `linkedRecordQueryResult` after a table deletion
29
+ - Update `children` prop of `Link` component to be optional
19
30
 
20
31
  ## [1.9.0](https://github.com/airtable/blocks/compare/@airtable/blocks@1.8.0...@airtable/blocks@1.9.0) - 2021-09-15
21
32
 
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "__esModule", {
8
8
  exports.spawnError = spawnError;
9
9
  exports.invariant = invariant;
10
10
  exports.spawnUnknownSwitchCaseError = spawnUnknownSwitchCaseError;
11
- exports.spawnExhaustiveSwitchError = spawnExhaustiveSwitchError;
12
11
  exports.spawnAbstractMethodError = spawnAbstractMethodError;
13
12
 
14
13
  // If errorOriginFn is specified, all frames above and including the call to errorOriginFn
@@ -80,22 +79,6 @@ function spawnUnknownSwitchCaseError(valueDescription, providedValue, key) {
80
79
  var providedValueKeyString = providedValueKey !== null && providedValueKey !== undefined ? providedValueKey : 'null';
81
80
  return spawnErrorWithOriginOmittedFromStackTrace('Unknown value %s for %s', [providedValueKeyString, valueDescription], spawnUnknownSwitchCaseError);
82
81
  }
83
- /**
84
- * Forces TypeScript to prove that calling this function is impossible at a
85
- * type level by accepting `never`. In the unlikely case this function is
86
- * called we infer a useful error message.
87
- *
88
- * @internal
89
- */
90
-
91
-
92
- function spawnExhaustiveSwitchError(impossibleValue) {
93
- if (impossibleValue === null) {
94
- return spawnErrorWithOriginOmittedFromStackTrace('Unexpected null in exhaustive switch', undefined, spawnExhaustiveSwitchError);
95
- } else {
96
- return spawnErrorWithOriginOmittedFromStackTrace("Unexpected %s in exhaustive switch", [typeof impossibleValue], spawnExhaustiveSwitchError);
97
- }
98
- }
99
82
  /**
100
83
  * @internal
101
84
  */
@@ -245,13 +245,19 @@ function (_RecordQueryResult) {
245
245
  while (1) {
246
246
  switch (_context2.prev = _context2.next) {
247
247
  case 0:
248
- // TODO: This entire class assumes it is torn down and re-created by the parent whenever
249
- // a change to the group is made.
250
- this._parentQueryResult.__groupedRecordQueryResultPool.registerObjectForReuseStrong(this);
248
+ this._parentQueryResult.__groupedRecordQueryResultPool.registerObjectForReuseStrong(this); // Ensure we invalidate our memoized computed recordIds whenever a relevant hook changes
249
+ // TODO: (SeanKeenan) At the moment this should never be relevant, because groups are recreated
250
+ // anytime the groups change - but this is how it should work once groups persist AND
251
+ // watching recordIds only changes if records in this group change.
252
+ // In the meantime this does ensure that a deleted GroupedRecordQuery with stale recordIds
253
+ // doesn't return the cached array.
251
254
 
255
+
256
+ this.watch(['recordIds', 'groups', 'groupLevels'], this._invalidateComputedRecordIds, this);
257
+ this.watch(['recordIds'], this._invalidateRecordIdsSet, this);
252
258
  return _context2.abrupt("return", this._getChangedKeysOnLoad());
253
259
 
254
- case 2:
260
+ case 4:
255
261
  case "end":
256
262
  return _context2.stop();
257
263
  }
@@ -263,7 +269,10 @@ function (_RecordQueryResult) {
263
269
  }, {
264
270
  key: "_unloadData",
265
271
  value: function _unloadData() {
266
- // Invalidate both of the caches, as this object can no longer be accessed
272
+ // Ensure we invalidate our memoized computed recordIds whenever a relevant hook changes
273
+ this.unwatch(['recordIds', 'groups', 'groupLevels'], this._invalidateComputedRecordIds, this);
274
+ this.unwatch(['recordIds'], this._invalidateRecordIdsSet, this); // Invalidate both of the caches, as this object can no longer be accessed
275
+
267
276
  this._invalidateComputedRecordIds();
268
277
 
269
278
  this._invalidateRecordIdsSet();
@@ -29,8 +29,6 @@ Object.defineProperty(exports, "__esModule", {
29
29
  });
30
30
  exports.default = exports.getLinkedTableId = void 0;
31
31
 
32
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
33
-
34
32
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
35
33
 
36
34
  require("regenerator-runtime/runtime");
@@ -55,12 +53,8 @@ var _field = require("../types/field");
55
53
 
56
54
  var _error_utils = require("../error_utils");
57
55
 
58
- var _block_query_spec = require("../types/block_query_spec");
59
-
60
56
  var _record_query_result = _interopRequireDefault(require("./record_query_result"));
61
57
 
62
- var _record_store = require("./record_store");
63
-
64
58
  /** @module @airtable/blocks/models: RecordQueryResult */
65
59
 
66
60
  /** */
@@ -124,8 +118,6 @@ function (_RecordQueryResult) {
124
118
 
125
119
  /** @internal */
126
120
 
127
- /** @internal */
128
-
129
121
  /** @internal */
130
122
  function LinkedRecordsQueryResult(record, field, normalizedOpts, sdk) {
131
123
  var _this;
@@ -142,7 +134,6 @@ function (_RecordQueryResult) {
142
134
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_computedRecordIdsSet", null);
143
135
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_computedFilteredSortedRecordIds", null);
144
136
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_cellValueChangeHandlerByFieldId", {});
145
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_recordStoreQueryId", null);
146
137
  (0, _error_utils.invariant)(record.parentTable === field.parentTable, 'record and field must belong to the same table');
147
138
  _this._record = record;
148
139
  _this._field = field;
@@ -288,7 +279,7 @@ function (_RecordQueryResult) {
288
279
  }, {
289
280
  key: "_loadDataAsync",
290
281
  value: function _loadDataAsync() {
291
- var initiallyLoaded, _ref, _ref2, recordStoreQueryId, changedKeys, fieldIds, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, fieldId;
282
+ var initiallyLoaded, changedKeys, fieldIds, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, fieldId;
292
283
 
293
284
  return _regenerator.default.async(function _loadDataAsync$(_context2) {
294
285
  while (1) {
@@ -300,21 +291,11 @@ function (_RecordQueryResult) {
300
291
 
301
292
  this._watchLinkedQueryResult();
302
293
 
303
- initiallyLoaded = this._linkedQueryResult.isDataLoaded; // https://airtable.com/appahuJQw7qfQTBBU/tblSbpimM8Spp9txp/viweAFIus3MhU9Gxa/recNjFYJpeV23LPhH?blocks=hide
304
- // TODO: (#proj-blocks-sdk-record-limits) Currently queries all cell values in a table
305
- // when loading linked record data. Must add a LinkedRecord query type in the future.
306
- // Since _loadDataAsync can only be called once, this recordStoreQueryId is only set once,
307
- // although it is guaranteed to be stable if needed (so long as this._field.id is stable)
308
-
294
+ initiallyLoaded = this._linkedQueryResult.isDataLoaded;
309
295
  _context2.next = 6;
310
- return _regenerator.default.awrap(Promise.all([this._sdk.base.__getRecordStore(this._record.parentTable.id).loadAllCellValuesInFieldIdsAsync([this._field.id]), this._linkedQueryResult.loadDataAsync(), this._loadRecordColorsAsync()]));
296
+ return _regenerator.default.awrap(Promise.all([this._sdk.base.__getRecordStore(this._record.parentTable.id).loadCellValuesInFieldIdsAsync([this._field.id]), this._linkedQueryResult.loadDataAsync(), this._loadRecordColorsAsync()]));
311
297
 
312
298
  case 6:
313
- _ref = _context2.sent;
314
- _ref2 = (0, _slicedToArray2.default)(_ref, 1);
315
- recordStoreQueryId = _ref2[0];
316
- this._recordStoreQueryId = recordStoreQueryId;
317
-
318
299
  this._invalidateComputedData();
319
300
 
320
301
  changedKeys = ['records', 'recordIds', 'recordColors']; // If the linked query result was not initially loaded, then the
@@ -330,55 +311,55 @@ function (_RecordQueryResult) {
330
311
  _iteratorNormalCompletion3 = true;
331
312
  _didIteratorError3 = false;
332
313
  _iteratorError3 = undefined;
333
- _context2.prev = 17;
314
+ _context2.prev = 13;
334
315
 
335
316
  for (_iterator3 = fieldIds[Symbol.iterator](); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
336
317
  fieldId = _step3.value;
337
318
  changedKeys.push(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId);
338
319
  }
339
320
 
340
- _context2.next = 25;
321
+ _context2.next = 21;
341
322
  break;
342
323
 
343
- case 21:
344
- _context2.prev = 21;
345
- _context2.t0 = _context2["catch"](17);
324
+ case 17:
325
+ _context2.prev = 17;
326
+ _context2.t0 = _context2["catch"](13);
346
327
  _didIteratorError3 = true;
347
328
  _iteratorError3 = _context2.t0;
348
329
 
349
- case 25:
350
- _context2.prev = 25;
351
- _context2.prev = 26;
330
+ case 21:
331
+ _context2.prev = 21;
332
+ _context2.prev = 22;
352
333
 
353
334
  if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
354
335
  _iterator3.return();
355
336
  }
356
337
 
357
- case 28:
358
- _context2.prev = 28;
338
+ case 24:
339
+ _context2.prev = 24;
359
340
 
360
341
  if (!_didIteratorError3) {
361
- _context2.next = 31;
342
+ _context2.next = 27;
362
343
  break;
363
344
  }
364
345
 
365
346
  throw _iteratorError3;
366
347
 
367
- case 31:
368
- return _context2.finish(28);
348
+ case 27:
349
+ return _context2.finish(24);
369
350
 
370
- case 32:
371
- return _context2.finish(25);
351
+ case 28:
352
+ return _context2.finish(21);
372
353
 
373
- case 33:
354
+ case 29:
374
355
  return _context2.abrupt("return", changedKeys);
375
356
 
376
- case 34:
357
+ case 30:
377
358
  case "end":
378
359
  return _context2.stop();
379
360
  }
380
361
  }
381
- }, null, this, [[17, 21, 25, 33], [26,, 28, 32]]);
362
+ }, null, this, [[13, 17, 21, 29], [22,, 24, 28]]);
382
363
  }
383
364
  /** @internal */
384
365
 
@@ -395,9 +376,7 @@ function (_RecordQueryResult) {
395
376
 
396
377
  this._unwatchLinkedQueryResult();
397
378
 
398
- (0, _error_utils.invariant)(this._recordStoreQueryId, 'Unsubscribing from linked record record store without queryId');
399
-
400
- this._sdk.base.__getRecordStore(this._record.parentTable.id).unloadCellValuesForQueryIdsThatAreSubscribedToAllCells([this._recordStoreQueryId]);
379
+ this._originRecordStore.unloadCellValuesInFieldIds([this._field.id]);
401
380
 
402
381
  this._linkedQueryResult.unloadData();
403
382
 
@@ -469,12 +448,7 @@ function (_RecordQueryResult) {
469
448
  // result
470
449
 
471
450
 
472
- this._originRecordStore.watchWithRecordQueryResult({
473
- recordQueryResult: this,
474
- keys: _record_store.WatchableRecordStoreKeys.recordIds,
475
- callbackForRegistration: this._onOriginRecordsChange,
476
- context: this
477
- }); // if the linked field in the origin table is deleted, we need to
451
+ this._originRecordStore.watch('recordIds', this._onOriginRecordsChange, this); // if the linked field in the origin table is deleted, we need to
478
452
  // invalidate this result
479
453
 
480
454
 
@@ -618,12 +592,11 @@ function (_RecordQueryResult) {
618
592
  if (Array.isArray(recordIds)) {
619
593
  var recordIdsSet = this._getOrGenerateRecordIdsSet();
620
594
 
621
- var filteredRecordIds = recordIds.filter(id => typeof id === 'string' && recordIdsSet[id] === true); // There should always be a filteredRecordIds found for this query
622
- // type - not finding any is a fundamental mistake in our query engine
595
+ var filteredRecordIds = recordIds.filter(id => typeof id === 'string' && recordIdsSet[id] === true);
623
596
 
624
- (0, _error_utils.invariant)(filteredRecordIds.length, 'Filtered record change on incorrect record, query engine issue');
625
-
626
- this._onChange(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId, filteredRecordIds);
597
+ if (filteredRecordIds.length) {
598
+ this._onChange(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId, filteredRecordIds);
599
+ }
627
600
  } else {
628
601
  this._onChange(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId);
629
602
  }
@@ -803,27 +776,6 @@ function (_RecordQueryResult) {
803
776
  (0, _error_utils.invariant)(recordIdsSet, 'recordIdsSet must exist');
804
777
  return recordIdsSet;
805
778
  }
806
- /**
807
- * This allows a record query result to specify the source of the query
808
- * eg: View, Table, Linked record when watching fields.
809
- * This scopes the watch to those fields + rows in the query.
810
- *
811
- * @internal
812
- */
813
-
814
- }, {
815
- key: "__constructQuerySpecForBlockFieldSelectionSpec",
816
- value: function __constructQuerySpecForBlockFieldSelectionSpec(fieldSelection) {
817
- // The origin tableId is always the one referred to here as we must watch the origin record for deletion
818
- var originTableId = this._record.parentTable.id;
819
- return {
820
- sourceType: _block_query_spec.BlockQuerySourceType.TABLE,
821
- sourceTableId: originTableId,
822
- recordSelection: {
823
- fieldSelection
824
- }
825
- };
826
- }
827
779
  }, {
828
780
  key: "isValid",
829
781
  get: function get() {
@@ -6,12 +6,18 @@ 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.filter");
10
+
11
+ require("core-js/modules/es.array.flat-map");
12
+
9
13
  require("core-js/modules/es.array.includes");
10
14
 
11
15
  require("core-js/modules/es.array.iterator");
12
16
 
13
17
  require("core-js/modules/es.array.map");
14
18
 
19
+ require("core-js/modules/es.array.unscopables.flat-map");
20
+
15
21
  require("core-js/modules/es.object.to-string");
16
22
 
17
23
  require("core-js/modules/es.promise");
@@ -22,11 +28,15 @@ require("core-js/modules/es.string.includes");
22
28
 
23
29
  require("core-js/modules/web.dom-collections.iterator");
24
30
 
31
+ require("core-js/modules/web.url.to-json");
32
+
25
33
  Object.defineProperty(exports, "__esModule", {
26
34
  value: true
27
35
  });
28
36
  exports.default = void 0;
29
37
 
38
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
39
+
30
40
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
31
41
 
32
42
  require("regenerator-runtime/runtime");
@@ -41,6 +51,8 @@ var _airtable_interface = require("../types/airtable_interface");
41
51
 
42
52
  var _mutations = require("../types/mutations");
43
53
 
54
+ var _private_utils = require("../private_utils");
55
+
44
56
  var _error_utils = require("../error_utils");
45
57
 
46
58
  var _mutation_constants = require("./mutation_constants");
@@ -69,18 +81,22 @@ function () {
69
81
 
70
82
  /** @internal */
71
83
 
84
+ /** @internal */
85
+
72
86
  /** @hidden */
73
- function Mutations(sdk, session, base, applyGlobalConfigUpdates) {
87
+ function Mutations(sdk, session, base, applyModelChanges, applyGlobalConfigUpdates) {
74
88
  (0, _classCallCheck2.default)(this, Mutations);
75
89
  (0, _defineProperty2.default)(this, "_airtableInterface", void 0);
76
90
  (0, _defineProperty2.default)(this, "_session", void 0);
77
91
  (0, _defineProperty2.default)(this, "_sdk", void 0);
78
92
  (0, _defineProperty2.default)(this, "_base", void 0);
93
+ (0, _defineProperty2.default)(this, "_applyModelChanges", void 0);
79
94
  (0, _defineProperty2.default)(this, "_applyGlobalConfigUpdates", void 0);
80
95
  this._airtableInterface = sdk.__airtableInterface;
81
96
  this._session = session;
82
97
  this._sdk = sdk;
83
98
  this._base = base;
99
+ this._applyModelChanges = applyModelChanges;
84
100
  this._applyGlobalConfigUpdates = applyGlobalConfigUpdates;
85
101
  }
86
102
  /** @hidden */
@@ -254,12 +270,9 @@ function () {
254
270
  try {
255
271
  for (var _iterator = records[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
256
272
  var record = _step.value;
257
- var existingRecord = null; // Note - if isSubscribedToAllRecordsInTable is true then we know the record
258
- // doesn't exist (or is deleted) but otherwise we can issue a mutation to a record
259
- // that does not exist, having to deal with the error thrown by PublicAirtableInterfaceFrontend
260
- // TODO: (#proj-blocks-sdk-record-limits) Write tests around this behavior
273
+ var existingRecord = null;
261
274
 
262
- if (recordStore.isSubscribedToAllRecordsInTable || recordStore.isRecordLoaded(record.id)) {
275
+ if (recordStore.isRecordMetadataLoaded) {
263
276
  existingRecord = recordStore.getRecordByIdIfExists(record.id);
264
277
 
265
278
  if (!existingRecord) {
@@ -281,7 +294,7 @@ function () {
281
294
  checkedFieldIds.add(fieldId);
282
295
  }
283
296
 
284
- if (existingRecord && recordStore.isRecordCellValueLoadedForFieldId(record.id, fieldId)) {
297
+ if (existingRecord && recordStore.areCellValuesLoadedForFieldId(fieldId)) {
285
298
  var validationResult = this._airtableInterface.fieldTypeProvider.validateCellValueForUpdate(appInterface, record.cellValuesByFieldId[fieldId], existingRecord._getRawCellValue(field), field._data);
286
299
 
287
300
  if (!validationResult.isValid) {
@@ -319,15 +332,9 @@ function () {
319
332
  throw (0, _error_utils.spawnError)("Can't delete records: No table with id %s exists", _tableId);
320
333
  }
321
334
 
322
- var _recordStore = this._base.__getRecordStore(_tableId); // TODO: (#proj-blocks-sdk-record-limits) We substantially weaken our check here
323
- // because we can only be sure if the record exists inside the SDK if we've loaded
324
- // all records. It is possible to change this logic to ensure we don't double-delete
325
- // records by caching previously deleted records (if the delete is undone, but
326
- // we're not watching the record be re-created from the undo we would have to fail
327
- // the delete if we detect double deletion). TODO to add tests around this behavior.
328
-
335
+ var _recordStore = this._base.__getRecordStore(_tableId);
329
336
 
330
- if (_recordStore.isSubscribedToAllRecordsInTable) {
337
+ if (_recordStore.isRecordMetadataLoaded) {
331
338
  var _iteratorNormalCompletion2 = true;
332
339
  var _didIteratorError2 = false;
333
340
  var _iteratorError2 = undefined;
@@ -665,13 +672,150 @@ function () {
665
672
  this._applyGlobalConfigUpdates(mutation.updates);
666
673
 
667
674
  return true;
668
- } // https://airtable.com/appahuJQw7qfQTBBU/tblSbpimM8Spp9txp/viweAFIus3MhU9Gxa/recHOckY4V9QmM6JV?blocks=hide
669
- // TODO: (#proj-blocks-sdk-record-limits) Fix this in a future stacked diff where optimistic
670
- // updates are re-enabled https://docs.google.com/document/d/1CVZ4ZoPWEtpzKq_9cRLASGwgY71WI4nl6RVvs8S7Ubw/edit#
675
+ }
676
+
677
+ var modelChanges = this._getOptimisticModelChangesForMutation(mutation);
671
678
 
679
+ if (modelChanges.length > 0) {
680
+ this._applyModelChanges(modelChanges);
681
+
682
+ return true;
683
+ }
672
684
 
673
685
  return false;
674
686
  }
687
+ /** @internal */
688
+
689
+ }, {
690
+ key: "_getOptimisticModelChangesForMutation",
691
+ value: function _getOptimisticModelChangesForMutation(mutation) {
692
+ switch (mutation.type) {
693
+ case _mutations.MutationTypes.SET_MULTIPLE_RECORDS_CELL_VALUES:
694
+ {
695
+ var tableId = mutation.tableId,
696
+ records = mutation.records;
697
+
698
+ var recordStore = this._base.__getRecordStore(tableId);
699
+
700
+ return records.flatMap(record => Object.keys(record.cellValuesByFieldId).filter(fieldId => recordStore.areCellValuesLoadedForFieldId(fieldId)).map(fieldId => ({
701
+ path: ['tablesById', tableId, 'recordsById', record.id, 'cellValuesByFieldId', fieldId],
702
+ value: record.cellValuesByFieldId[fieldId]
703
+ })));
704
+ }
705
+
706
+ case _mutations.MutationTypes.DELETE_MULTIPLE_RECORDS:
707
+ {
708
+ var _tableId7 = mutation.tableId,
709
+ recordIds = mutation.recordIds;
710
+
711
+ var _recordStore2 = this._base.__getRecordStore(_tableId7);
712
+
713
+ if (!_recordStore2.isRecordMetadataLoaded) {
714
+ return [];
715
+ }
716
+
717
+ return [...recordIds.map(recordId => ({
718
+ path: ['tablesById', _tableId7, 'recordsById', recordId],
719
+ value: undefined
720
+ })), ...this._base.getTableById(_tableId7).views.flatMap(view => {
721
+ var viewDataStore = _recordStore2.getViewDataStore(view.id);
722
+
723
+ if (!viewDataStore.isDataLoaded) {
724
+ return [];
725
+ }
726
+
727
+ return viewDataStore.__generateChangesForParentTableDeleteMultipleRecords(recordIds);
728
+ })];
729
+ }
730
+
731
+ case _mutations.MutationTypes.CREATE_MULTIPLE_RECORDS:
732
+ {
733
+ var _tableId8 = mutation.tableId,
734
+ _records2 = mutation.records;
735
+
736
+ var _recordStore3 = this._base.__getRecordStore(_tableId8);
737
+
738
+ if (!_recordStore3.isRecordMetadataLoaded) {
739
+ return [];
740
+ }
741
+
742
+ return [..._records2.map(record => {
743
+ // Only apply optimistic changes for fields that are loaded
744
+ var filteredCellValuesByFieldId = {};
745
+ var _iteratorNormalCompletion5 = true;
746
+ var _didIteratorError5 = false;
747
+ var _iteratorError5 = undefined;
748
+
749
+ try {
750
+ for (var _iterator5 = (0, _private_utils.entries)(record.cellValuesByFieldId)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
751
+ var _step5$value = (0, _slicedToArray2.default)(_step5.value, 2),
752
+ fieldId = _step5$value[0],
753
+ cellValue = _step5$value[1];
754
+
755
+ if (_recordStore3.areCellValuesLoadedForFieldId(fieldId)) {
756
+ filteredCellValuesByFieldId[fieldId] = cellValue;
757
+ }
758
+ }
759
+ } catch (err) {
760
+ _didIteratorError5 = true;
761
+ _iteratorError5 = err;
762
+ } finally {
763
+ try {
764
+ if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
765
+ _iterator5.return();
766
+ }
767
+ } finally {
768
+ if (_didIteratorError5) {
769
+ throw _iteratorError5;
770
+ }
771
+ }
772
+ }
773
+
774
+ return {
775
+ path: ['tablesById', _tableId8, 'recordsById', record.id],
776
+ value: {
777
+ id: record.id,
778
+ cellValuesByFieldId: filteredCellValuesByFieldId,
779
+ commentCount: 0,
780
+ createdTime: new Date().toJSON()
781
+ }
782
+ };
783
+ }), ...this._base.getTableById(_tableId8).views.flatMap(view => {
784
+ var viewDataStore = _recordStore3.getViewDataStore(view.id);
785
+
786
+ if (!viewDataStore.isDataLoaded) {
787
+ return [];
788
+ }
789
+
790
+ return viewDataStore.__generateChangesForParentTableAddMultipleRecords(_records2.map(record => record.id));
791
+ })];
792
+ }
793
+ // The following branch is unreachable because this method's only
794
+ // call site is preceded by an explicit guard for this condition.
795
+ // istanbul ignore next
796
+
797
+ case _mutations.MutationTypes.SET_MULTIPLE_GLOBAL_CONFIG_PATHS:
798
+ {
799
+ throw (0, _error_utils.spawnError)('attempting to generate model updates for SET_MULTIPLE_GLOBAL_CONFIG_PATH');
800
+ }
801
+
802
+ case _mutations.MutationTypes.CREATE_SINGLE_FIELD:
803
+ case _mutations.MutationTypes.UPDATE_SINGLE_FIELD_CONFIG:
804
+ case _mutations.MutationTypes.UPDATE_SINGLE_FIELD_DESCRIPTION:
805
+ case _mutations.MutationTypes.UPDATE_VIEW_METADATA:
806
+ case _mutations.MutationTypes.CREATE_SINGLE_TABLE:
807
+ {
808
+ // No optimistic updates for field, view metadata, or table mutations.
809
+ return [];
810
+ }
811
+ // The following branch is unreachable because this method's only
812
+ // call site is preceded by an explicit guard for this condition.
813
+ // istanbul ignore next
814
+
815
+ default:
816
+ throw (0, _error_utils.spawnUnknownSwitchCaseError)('mutation type', mutation, 'type');
817
+ }
818
+ }
675
819
  }]);
676
820
  return Mutations;
677
821
  }();