@airtable/blocks 1.7.0 → 1.9.0-experimental

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 (98) hide show
  1. package/CHANGELOG.md +29 -3
  2. package/dist/cjs/error_utils.js +17 -0
  3. package/dist/cjs/models/base.js +16 -11
  4. package/dist/cjs/models/cursor.js +2 -0
  5. package/dist/cjs/models/field.js +157 -36
  6. package/dist/cjs/models/grouped_record_query_result.js +5 -14
  7. package/dist/cjs/models/linked_records_query_result.js +75 -27
  8. package/dist/cjs/models/mutation_constants.js +3 -1
  9. package/dist/cjs/models/mutations.js +70 -178
  10. package/dist/cjs/models/query_manager.js +327 -0
  11. package/dist/cjs/models/record.js +308 -55
  12. package/dist/cjs/models/record_query_result.js +4 -1
  13. package/dist/cjs/models/record_store.js +554 -765
  14. package/dist/cjs/models/table.js +22 -19
  15. package/dist/cjs/models/table_or_view_query_result.js +480 -414
  16. package/dist/cjs/models/view_data_store.js +243 -269
  17. package/dist/cjs/private_utils.js +50 -0
  18. package/dist/cjs/sdk.js +12 -2
  19. package/dist/cjs/testing/{mock_airtable_interface.js → abstract_mock_airtable_interface.js} +71 -22
  20. package/dist/cjs/types/block_query_spec.js +85 -0
  21. package/dist/cjs/types/field.js +1 -0
  22. package/dist/cjs/types/mutations.js +1 -0
  23. package/dist/cjs/ui/icon_config.js +6 -2
  24. package/dist/cjs/ui/use_global_config.js +1 -1
  25. package/dist/cjs/ui/use_records.js +5 -1
  26. package/dist/cjs/unstable_testing_utils.js +2 -2
  27. package/dist/cjs/watchable.js +123 -71
  28. package/dist/types/src/models/base.d.ts +10 -9
  29. package/dist/types/src/models/base.d.ts.map +1 -1
  30. package/dist/types/src/models/cursor.d.ts +2 -0
  31. package/dist/types/src/models/cursor.d.ts.map +1 -1
  32. package/dist/types/src/models/field.d.ts +71 -9
  33. package/dist/types/src/models/field.d.ts.map +1 -1
  34. package/dist/types/src/models/grouped_record_query_result.d.ts +3 -3
  35. package/dist/types/src/models/grouped_record_query_result.d.ts.map +1 -1
  36. package/dist/types/src/models/linked_records_query_result.d.ts.map +1 -1
  37. package/dist/types/src/models/mutation_constants.d.ts +1 -0
  38. package/dist/types/src/models/mutation_constants.d.ts.map +1 -1
  39. package/dist/types/src/models/mutations.d.ts.map +1 -1
  40. package/dist/types/src/models/query_manager.d.ts +2 -0
  41. package/dist/types/src/models/query_manager.d.ts.map +1 -0
  42. package/dist/types/src/models/record.d.ts +12 -3
  43. package/dist/types/src/models/record.d.ts.map +1 -1
  44. package/dist/types/src/models/record_query_result.d.ts +3 -2
  45. package/dist/types/src/models/record_query_result.d.ts.map +1 -1
  46. package/dist/types/src/models/record_store.d.ts.map +1 -1
  47. package/dist/types/src/models/table.d.ts +8 -10
  48. package/dist/types/src/models/table.d.ts.map +1 -1
  49. package/dist/types/src/models/table_or_view_query_result.d.ts +3 -5
  50. package/dist/types/src/models/table_or_view_query_result.d.ts.map +1 -1
  51. package/dist/types/src/models/view_data_store.d.ts +0 -1
  52. package/dist/types/src/models/view_data_store.d.ts.map +1 -1
  53. package/dist/types/src/models/view_metadata_query_result.d.ts +1 -1
  54. package/dist/types/src/models/view_metadata_query_result.d.ts.map +1 -1
  55. package/dist/types/src/private_utils.d.ts +30 -1
  56. package/dist/types/src/private_utils.d.ts.map +1 -1
  57. package/dist/types/src/sdk.d.ts.map +1 -1
  58. package/dist/types/src/testing/{mock_airtable_interface.d.ts → abstract_mock_airtable_interface.d.ts} +20 -15
  59. package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts.map +1 -0
  60. package/dist/types/src/types/airtable_interface.d.ts +45 -21
  61. package/dist/types/src/types/airtable_interface.d.ts.map +1 -1
  62. package/dist/types/src/types/block_query_spec.d.ts +139 -0
  63. package/dist/types/src/types/block_query_spec.d.ts.map +1 -0
  64. package/dist/types/src/types/field.d.ts +167 -51
  65. package/dist/types/src/types/field.d.ts.map +1 -1
  66. package/dist/types/src/types/mutations.d.ts +46 -3
  67. package/dist/types/src/types/mutations.d.ts.map +1 -1
  68. package/dist/types/src/types/table.d.ts +0 -2
  69. package/dist/types/src/types/table.d.ts.map +1 -1
  70. package/dist/types/src/types/view.d.ts +3 -8
  71. package/dist/types/src/types/view.d.ts.map +1 -1
  72. package/dist/types/src/ui/icon_config.d.ts +7 -3
  73. package/dist/types/src/ui/icon_config.d.ts.map +1 -1
  74. package/dist/types/src/ui/link.d.ts +1 -1
  75. package/dist/types/src/ui/link.d.ts.map +1 -1
  76. package/dist/types/src/ui/use_global_config.d.ts +1 -1
  77. package/dist/types/src/unstable_testing_utils.d.ts +1 -1
  78. package/dist/types/src/unstable_testing_utils.d.ts.map +1 -1
  79. package/dist/types/src/watchable.d.ts.map +1 -1
  80. package/dist/types/stories/helpers/fake_cell_renderer.d.ts.map +1 -1
  81. package/dist/types/stories/helpers/field_type.d.ts.map +1 -1
  82. package/dist/types/stories/helpers/sync_source_options.d.ts +7 -0
  83. package/dist/types/stories/helpers/sync_source_options.d.ts.map +1 -0
  84. package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts +121 -0
  85. package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts.map +1 -0
  86. package/dist/types/test/airtable_interface_mocks/linked_records.d.ts +2 -2
  87. package/dist/types/test/airtable_interface_mocks/linked_records.d.ts.map +1 -1
  88. package/dist/types/test/airtable_interface_mocks/{mock_airtable_interface_internal.d.ts → mock_airtable_interface.d.ts} +26 -18
  89. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts.map +1 -0
  90. package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts +51 -0
  91. package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts.map +1 -0
  92. package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts +2 -2
  93. package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts.map +1 -1
  94. package/dist/types/test/test_helpers.d.ts +2 -0
  95. package/dist/types/test/test_helpers.d.ts.map +1 -1
  96. package/package.json +3 -1
  97. package/dist/types/src/testing/mock_airtable_interface.d.ts.map +0 -1
  98. package/dist/types/test/airtable_interface_mocks/mock_airtable_interface_internal.d.ts.map +0 -1
@@ -29,6 +29,8 @@ 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
+
32
34
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
33
35
 
34
36
  require("regenerator-runtime/runtime");
@@ -53,8 +55,12 @@ var _field = require("../types/field");
53
55
 
54
56
  var _error_utils = require("../error_utils");
55
57
 
58
+ var _block_query_spec = require("../types/block_query_spec");
59
+
56
60
  var _record_query_result = _interopRequireDefault(require("./record_query_result"));
57
61
 
62
+ var _record_store = require("./record_store");
63
+
58
64
  /** @module @airtable/blocks/models: RecordQueryResult */
59
65
 
60
66
  /** */
@@ -118,6 +124,8 @@ function (_RecordQueryResult) {
118
124
 
119
125
  /** @internal */
120
126
 
127
+ /** @internal */
128
+
121
129
  /** @internal */
122
130
  function LinkedRecordsQueryResult(record, field, normalizedOpts, sdk) {
123
131
  var _this;
@@ -134,6 +142,7 @@ function (_RecordQueryResult) {
134
142
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_computedRecordIdsSet", null);
135
143
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_computedFilteredSortedRecordIds", null);
136
144
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_cellValueChangeHandlerByFieldId", {});
145
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_recordStoreQueryId", null);
137
146
  (0, _error_utils.invariant)(record.parentTable === field.parentTable, 'record and field must belong to the same table');
138
147
  _this._record = record;
139
148
  _this._field = field;
@@ -279,7 +288,7 @@ function (_RecordQueryResult) {
279
288
  }, {
280
289
  key: "_loadDataAsync",
281
290
  value: function _loadDataAsync() {
282
- var initiallyLoaded, changedKeys, fieldIds, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, fieldId;
291
+ var initiallyLoaded, _ref, _ref2, recordStoreQueryId, changedKeys, fieldIds, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, fieldId;
283
292
 
284
293
  return _regenerator.default.async(function _loadDataAsync$(_context2) {
285
294
  while (1) {
@@ -291,11 +300,21 @@ function (_RecordQueryResult) {
291
300
 
292
301
  this._watchLinkedQueryResult();
293
302
 
294
- initiallyLoaded = this._linkedQueryResult.isDataLoaded;
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
+
295
309
  _context2.next = 6;
296
- return _regenerator.default.awrap(Promise.all([this._sdk.base.__getRecordStore(this._record.parentTable.id).loadCellValuesInFieldIdsAsync([this._field.id]), this._linkedQueryResult.loadDataAsync(), this._loadRecordColorsAsync()]));
310
+ return _regenerator.default.awrap(Promise.all([this._sdk.base.__getRecordStore(this._record.parentTable.id).loadAllCellValuesInFieldIdsAsync([this._field.id]), this._linkedQueryResult.loadDataAsync(), this._loadRecordColorsAsync()]));
297
311
 
298
312
  case 6:
313
+ _ref = _context2.sent;
314
+ _ref2 = (0, _slicedToArray2.default)(_ref, 1);
315
+ recordStoreQueryId = _ref2[0];
316
+ this._recordStoreQueryId = recordStoreQueryId;
317
+
299
318
  this._invalidateComputedData();
300
319
 
301
320
  changedKeys = ['records', 'recordIds', 'recordColors']; // If the linked query result was not initially loaded, then the
@@ -311,55 +330,55 @@ function (_RecordQueryResult) {
311
330
  _iteratorNormalCompletion3 = true;
312
331
  _didIteratorError3 = false;
313
332
  _iteratorError3 = undefined;
314
- _context2.prev = 13;
333
+ _context2.prev = 17;
315
334
 
316
335
  for (_iterator3 = fieldIds[Symbol.iterator](); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
317
336
  fieldId = _step3.value;
318
337
  changedKeys.push(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId);
319
338
  }
320
339
 
321
- _context2.next = 21;
340
+ _context2.next = 25;
322
341
  break;
323
342
 
324
- case 17:
325
- _context2.prev = 17;
326
- _context2.t0 = _context2["catch"](13);
343
+ case 21:
344
+ _context2.prev = 21;
345
+ _context2.t0 = _context2["catch"](17);
327
346
  _didIteratorError3 = true;
328
347
  _iteratorError3 = _context2.t0;
329
348
 
330
- case 21:
331
- _context2.prev = 21;
332
- _context2.prev = 22;
349
+ case 25:
350
+ _context2.prev = 25;
351
+ _context2.prev = 26;
333
352
 
334
353
  if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
335
354
  _iterator3.return();
336
355
  }
337
356
 
338
- case 24:
339
- _context2.prev = 24;
357
+ case 28:
358
+ _context2.prev = 28;
340
359
 
341
360
  if (!_didIteratorError3) {
342
- _context2.next = 27;
361
+ _context2.next = 31;
343
362
  break;
344
363
  }
345
364
 
346
365
  throw _iteratorError3;
347
366
 
348
- case 27:
349
- return _context2.finish(24);
367
+ case 31:
368
+ return _context2.finish(28);
350
369
 
351
- case 28:
352
- return _context2.finish(21);
370
+ case 32:
371
+ return _context2.finish(25);
353
372
 
354
- case 29:
373
+ case 33:
355
374
  return _context2.abrupt("return", changedKeys);
356
375
 
357
- case 30:
376
+ case 34:
358
377
  case "end":
359
378
  return _context2.stop();
360
379
  }
361
380
  }
362
- }, null, this, [[13, 17, 21, 29], [22,, 24, 28]]);
381
+ }, null, this, [[17, 21, 25, 33], [26,, 28, 32]]);
363
382
  }
364
383
  /** @internal */
365
384
 
@@ -376,7 +395,9 @@ function (_RecordQueryResult) {
376
395
 
377
396
  this._unwatchLinkedQueryResult();
378
397
 
379
- this._sdk.base.__getRecordStore(this._record.parentTable.id).unloadCellValuesInFieldIds([this._field.id]);
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]);
380
401
 
381
402
  this._linkedQueryResult.unloadData();
382
403
 
@@ -448,7 +469,12 @@ function (_RecordQueryResult) {
448
469
  // result
449
470
 
450
471
 
451
- this._originRecordStore.watch('recordIds', this._onOriginRecordsChange, this); // if the linked field in the origin table is deleted, we need to
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
452
478
  // invalidate this result
453
479
 
454
480
 
@@ -592,11 +618,12 @@ function (_RecordQueryResult) {
592
618
  if (Array.isArray(recordIds)) {
593
619
  var recordIdsSet = this._getOrGenerateRecordIdsSet();
594
620
 
595
- var filteredRecordIds = recordIds.filter(id => typeof id === 'string' && recordIdsSet[id] === true);
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
596
623
 
597
- if (filteredRecordIds.length) {
598
- this._onChange(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId, filteredRecordIds);
599
- }
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);
600
627
  } else {
601
628
  this._onChange(_record_query_result.default.WatchableCellValuesInFieldKeyPrefix + fieldId);
602
629
  }
@@ -776,6 +803,27 @@ function (_RecordQueryResult) {
776
803
  (0, _error_utils.invariant)(recordIdsSet, 'recordIdsSet must exist');
777
804
  return recordIdsSet;
778
805
  }
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
+ }
779
827
  }, {
780
828
  key: "isValid",
781
829
  get: function get() {
@@ -3,10 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.MAX_NUM_FIELDS_PER_TABLE = exports.MAX_TABLE_NAME_LENGTH = exports.MAX_FIELD_NAME_LENGTH = void 0;
6
+ exports.MAX_NUM_FIELDS_PER_TABLE = exports.MAX_TABLE_NAME_LENGTH = exports.MAX_FIELD_DESCRIPTION_LENGTH = exports.MAX_FIELD_NAME_LENGTH = void 0;
7
7
  // Mirrored from clientServerSharedConfigSettings
8
8
  var MAX_FIELD_NAME_LENGTH = 255;
9
9
  exports.MAX_FIELD_NAME_LENGTH = MAX_FIELD_NAME_LENGTH;
10
+ var MAX_FIELD_DESCRIPTION_LENGTH = 20000;
11
+ exports.MAX_FIELD_DESCRIPTION_LENGTH = MAX_FIELD_DESCRIPTION_LENGTH;
10
12
  var MAX_TABLE_NAME_LENGTH = 255;
11
13
  exports.MAX_TABLE_NAME_LENGTH = MAX_TABLE_NAME_LENGTH;
12
14
  var MAX_NUM_FIELDS_PER_TABLE = 500;
@@ -6,18 +6,12 @@ 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
-
13
9
  require("core-js/modules/es.array.includes");
14
10
 
15
11
  require("core-js/modules/es.array.iterator");
16
12
 
17
13
  require("core-js/modules/es.array.map");
18
14
 
19
- require("core-js/modules/es.array.unscopables.flat-map");
20
-
21
15
  require("core-js/modules/es.object.to-string");
22
16
 
23
17
  require("core-js/modules/es.promise");
@@ -28,15 +22,11 @@ require("core-js/modules/es.string.includes");
28
22
 
29
23
  require("core-js/modules/web.dom-collections.iterator");
30
24
 
31
- require("core-js/modules/web.url.to-json");
32
-
33
25
  Object.defineProperty(exports, "__esModule", {
34
26
  value: true
35
27
  });
36
28
  exports.default = void 0;
37
29
 
38
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
39
-
40
30
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
41
31
 
42
32
  require("regenerator-runtime/runtime");
@@ -51,8 +41,6 @@ var _airtable_interface = require("../types/airtable_interface");
51
41
 
52
42
  var _mutations = require("../types/mutations");
53
43
 
54
- var _private_utils = require("../private_utils");
55
-
56
44
  var _error_utils = require("../error_utils");
57
45
 
58
46
  var _mutation_constants = require("./mutation_constants");
@@ -81,22 +69,18 @@ function () {
81
69
 
82
70
  /** @internal */
83
71
 
84
- /** @internal */
85
-
86
72
  /** @hidden */
87
- function Mutations(sdk, session, base, applyModelChanges, applyGlobalConfigUpdates) {
73
+ function Mutations(sdk, session, base, applyGlobalConfigUpdates) {
88
74
  (0, _classCallCheck2.default)(this, Mutations);
89
75
  (0, _defineProperty2.default)(this, "_airtableInterface", void 0);
90
76
  (0, _defineProperty2.default)(this, "_session", void 0);
91
77
  (0, _defineProperty2.default)(this, "_sdk", void 0);
92
78
  (0, _defineProperty2.default)(this, "_base", void 0);
93
- (0, _defineProperty2.default)(this, "_applyModelChanges", void 0);
94
79
  (0, _defineProperty2.default)(this, "_applyGlobalConfigUpdates", void 0);
95
80
  this._airtableInterface = sdk.__airtableInterface;
96
81
  this._session = session;
97
82
  this._sdk = sdk;
98
83
  this._base = base;
99
- this._applyModelChanges = applyModelChanges;
100
84
  this._applyGlobalConfigUpdates = applyGlobalConfigUpdates;
101
85
  }
102
86
  /** @hidden */
@@ -270,9 +254,12 @@ function () {
270
254
  try {
271
255
  for (var _iterator = records[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
272
256
  var record = _step.value;
273
- var existingRecord = null;
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
274
261
 
275
- if (recordStore.isRecordMetadataLoaded) {
262
+ if (recordStore.isSubscribedToAllRecordsInTable || recordStore.isRecordLoaded(record.id)) {
276
263
  existingRecord = recordStore.getRecordByIdIfExists(record.id);
277
264
 
278
265
  if (!existingRecord) {
@@ -294,7 +281,7 @@ function () {
294
281
  checkedFieldIds.add(fieldId);
295
282
  }
296
283
 
297
- if (existingRecord && recordStore.areCellValuesLoadedForFieldId(fieldId)) {
284
+ if (existingRecord && recordStore.isRecordCellValueLoadedForFieldId(record.id, fieldId)) {
298
285
  var validationResult = this._airtableInterface.fieldTypeProvider.validateCellValueForUpdate(appInterface, record.cellValuesByFieldId[fieldId], existingRecord._getRawCellValue(field), field._data);
299
286
 
300
287
  if (!validationResult.isValid) {
@@ -332,9 +319,15 @@ function () {
332
319
  throw (0, _error_utils.spawnError)("Can't delete records: No table with id %s exists", _tableId);
333
320
  }
334
321
 
335
- var _recordStore = this._base.__getRecordStore(_tableId);
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
+
336
329
 
337
- if (_recordStore.isRecordMetadataLoaded) {
330
+ if (_recordStore.isSubscribedToAllRecordsInTable) {
338
331
  var _iteratorNormalCompletion2 = true;
339
332
  var _didIteratorError2 = false;
340
333
  var _iteratorError2 = undefined;
@@ -442,7 +435,8 @@ function () {
442
435
  {
443
436
  var _tableId3 = mutation.tableId,
444
437
  name = mutation.name,
445
- config = mutation.config;
438
+ config = mutation.config,
439
+ description = mutation.description;
446
440
 
447
441
  var _table3 = this._base.getTableByIdIfExists(_tableId3);
448
442
 
@@ -475,6 +469,10 @@ function () {
475
469
  throw (0, _error_utils.spawnError)("Can't create field: invalid field config.\n%s", _validationResult2.reason);
476
470
  }
477
471
 
472
+ if (description && description.length > _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH) {
473
+ throw (0, _error_utils.spawnError)("Can't create field: description exceeds maximum length of %s characters", _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH);
474
+ }
475
+
478
476
  return;
479
477
  }
480
478
 
@@ -482,7 +480,8 @@ function () {
482
480
  {
483
481
  var _tableId4 = mutation.tableId,
484
482
  id = mutation.id,
485
- _config = mutation.config;
483
+ _config = mutation.config,
484
+ opts = mutation.opts;
486
485
 
487
486
  var _table4 = this._base.getTableByIdIfExists(_tableId4);
488
487
 
@@ -501,7 +500,7 @@ function () {
501
500
 
502
501
  var currentConfig = this._airtableInterface.fieldTypeProvider.getConfig(appInterface, _field2._data, _field2.parentTable.__getFieldNamesById());
503
502
 
504
- var _validationResult3 = this._airtableInterface.fieldTypeProvider.validateConfigForUpdate(appInterface, _config, currentConfig, _field2._data, billingPlanGrouping);
503
+ var _validationResult3 = this._airtableInterface.fieldTypeProvider.validateConfigForUpdate(appInterface, _config, currentConfig, _field2._data, billingPlanGrouping, opts);
505
504
 
506
505
  if (!_validationResult3.isValid) {
507
506
  throw (0, _error_utils.spawnError)("Can't update field: invalid field config.\n%s", _validationResult3.reason);
@@ -510,6 +509,31 @@ function () {
510
509
  return;
511
510
  }
512
511
 
512
+ case _mutations.MutationTypes.UPDATE_SINGLE_FIELD_DESCRIPTION:
513
+ {
514
+ var _tableId5 = mutation.tableId,
515
+ _id = mutation.id,
516
+ _description = mutation.description;
517
+
518
+ var _table5 = this._base.getTableByIdIfExists(_tableId5);
519
+
520
+ if (!_table5) {
521
+ throw (0, _error_utils.spawnError)("Can't update field: No table with id %s exists", _tableId5);
522
+ }
523
+
524
+ var _field3 = _table5.getFieldByIdIfExists(_id);
525
+
526
+ if (!_field3) {
527
+ throw (0, _error_utils.spawnError)("Can't update field: No field with id %s exists", _id);
528
+ }
529
+
530
+ if (_description && _description.length > _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH) {
531
+ throw (0, _error_utils.spawnError)("Can't update field: description exceeds maximum length of %s characters", _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH);
532
+ }
533
+
534
+ return;
535
+ }
536
+
513
537
  case _mutations.MutationTypes.CREATE_SINGLE_TABLE:
514
538
  {
515
539
  var _name = mutation.name,
@@ -544,28 +568,32 @@ function () {
544
568
 
545
569
  try {
546
570
  for (var _iterator4 = fields[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
547
- var _field3 = _step4.value;
571
+ var _field4 = _step4.value;
548
572
 
549
- if (!_field3.name) {
573
+ if (!_field4.name) {
550
574
  throw (0, _error_utils.spawnError)("Can't create table: must provide non-empty name for every field");
551
575
  }
552
576
 
553
- if (_field3.name.length > _mutation_constants.MAX_FIELD_NAME_LENGTH) {
554
- throw (0, _error_utils.spawnError)("Can't create table: field name '%s' exceeds maximum length of %s characters", _field3.name, _mutation_constants.MAX_FIELD_NAME_LENGTH);
577
+ if (_field4.name.length > _mutation_constants.MAX_FIELD_NAME_LENGTH) {
578
+ throw (0, _error_utils.spawnError)("Can't create table: field name '%s' exceeds maximum length of %s characters", _field4.name, _mutation_constants.MAX_FIELD_NAME_LENGTH);
555
579
  }
556
580
 
557
- var lowercaseFieldName = _field3.name.toLowerCase();
581
+ var lowercaseFieldName = _field4.name.toLowerCase();
558
582
 
559
583
  if (lowercaseFieldNames.has(lowercaseFieldName)) {
560
- throw (0, _error_utils.spawnError)("Can't create table: duplicate field name '%s'", _field3.name);
584
+ throw (0, _error_utils.spawnError)("Can't create table: duplicate field name '%s'", _field4.name);
561
585
  }
562
586
 
563
587
  lowercaseFieldNames.add(lowercaseFieldName); // Current config / field data is null since the field doesn't exist.
564
588
 
565
- var _validationResult4 = this._airtableInterface.fieldTypeProvider.validateConfigForUpdate(appInterface, _field3.config, null, null, billingPlanGrouping);
589
+ var _validationResult4 = this._airtableInterface.fieldTypeProvider.validateConfigForUpdate(appInterface, _field4.config, null, null, billingPlanGrouping);
566
590
 
567
591
  if (!_validationResult4.isValid) {
568
- throw (0, _error_utils.spawnError)("Can't create table: invalid field config for field '%s'.\n%s", _field3.name, _validationResult4.reason);
592
+ throw (0, _error_utils.spawnError)("Can't create table: invalid field config for field '%s'.\n%s", _field4.name, _validationResult4.reason);
593
+ }
594
+
595
+ if (_field4.description && _field4.description.length > _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH) {
596
+ throw (0, _error_utils.spawnError)("Can't create table: description for field '%s' exceeds maximum length of %s characters", _field4.name, _mutation_constants.MAX_FIELD_DESCRIPTION_LENGTH);
569
597
  }
570
598
  }
571
599
  } catch (err) {
@@ -594,7 +622,7 @@ function () {
594
622
 
595
623
  case _mutations.MutationTypes.UPDATE_VIEW_METADATA:
596
624
  {
597
- var _tableId5 = mutation.tableId,
625
+ var _tableId6 = mutation.tableId,
598
626
  viewId = mutation.viewId;
599
627
  var runContext = this._airtableInterface.sdkInitData.runContext;
600
628
 
@@ -602,17 +630,17 @@ function () {
602
630
  throw (0, _error_utils.spawnError)('Setting view metadata is only valid for views');
603
631
  }
604
632
 
605
- if (runContext.viewId !== viewId || runContext.tableId !== _tableId5) {
633
+ if (runContext.viewId !== viewId || runContext.tableId !== _tableId6) {
606
634
  throw (0, _error_utils.spawnError)('Custom views can only set view metadata on themselves');
607
635
  }
608
636
 
609
- var _table5 = this._base.getTableByIdIfExists(_tableId5);
637
+ var _table6 = this._base.getTableByIdIfExists(_tableId6);
610
638
 
611
- if (!_table5) {
612
- throw (0, _error_utils.spawnError)("Can't update metadata: No table with id %s exists", _tableId5);
639
+ if (!_table6) {
640
+ throw (0, _error_utils.spawnError)("Can't update metadata: No table with id %s exists", _tableId6);
613
641
  }
614
642
 
615
- var view = _table5.getViewByIdIfExists(viewId);
643
+ var view = _table6.getViewByIdIfExists(viewId);
616
644
 
617
645
  if (!view) {
618
646
  throw (0, _error_utils.spawnError)("Can't update metadata: No view with id %s exists", viewId);
@@ -637,149 +665,13 @@ function () {
637
665
  this._applyGlobalConfigUpdates(mutation.updates);
638
666
 
639
667
  return true;
640
- }
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#
641
671
 
642
- var modelChanges = this._getOptimisticModelChangesForMutation(mutation);
643
-
644
- if (modelChanges.length > 0) {
645
- this._applyModelChanges(modelChanges);
646
-
647
- return true;
648
- }
649
672
 
650
673
  return false;
651
674
  }
652
- /** @internal */
653
-
654
- }, {
655
- key: "_getOptimisticModelChangesForMutation",
656
- value: function _getOptimisticModelChangesForMutation(mutation) {
657
- switch (mutation.type) {
658
- case _mutations.MutationTypes.SET_MULTIPLE_RECORDS_CELL_VALUES:
659
- {
660
- var tableId = mutation.tableId,
661
- records = mutation.records;
662
-
663
- var recordStore = this._base.__getRecordStore(tableId);
664
-
665
- return records.flatMap(record => Object.keys(record.cellValuesByFieldId).filter(fieldId => recordStore.areCellValuesLoadedForFieldId(fieldId)).map(fieldId => ({
666
- path: ['tablesById', tableId, 'recordsById', record.id, 'cellValuesByFieldId', fieldId],
667
- value: record.cellValuesByFieldId[fieldId]
668
- })));
669
- }
670
-
671
- case _mutations.MutationTypes.DELETE_MULTIPLE_RECORDS:
672
- {
673
- var _tableId6 = mutation.tableId,
674
- recordIds = mutation.recordIds;
675
-
676
- var _recordStore2 = this._base.__getRecordStore(_tableId6);
677
-
678
- if (!_recordStore2.isRecordMetadataLoaded) {
679
- return [];
680
- }
681
-
682
- return [...recordIds.map(recordId => ({
683
- path: ['tablesById', _tableId6, 'recordsById', recordId],
684
- value: undefined
685
- })), ...this._base.getTableById(_tableId6).views.flatMap(view => {
686
- var viewDataStore = _recordStore2.getViewDataStore(view.id);
687
-
688
- if (!viewDataStore.isDataLoaded) {
689
- return [];
690
- }
691
-
692
- return viewDataStore.__generateChangesForParentTableDeleteMultipleRecords(recordIds);
693
- })];
694
- }
695
-
696
- case _mutations.MutationTypes.CREATE_MULTIPLE_RECORDS:
697
- {
698
- var _tableId7 = mutation.tableId,
699
- _records2 = mutation.records;
700
-
701
- var _recordStore3 = this._base.__getRecordStore(_tableId7);
702
-
703
- if (!_recordStore3.isRecordMetadataLoaded) {
704
- return [];
705
- }
706
-
707
- return [..._records2.map(record => {
708
- // Only apply optimistic changes for fields that are loaded
709
- var filteredCellValuesByFieldId = {};
710
- var _iteratorNormalCompletion5 = true;
711
- var _didIteratorError5 = false;
712
- var _iteratorError5 = undefined;
713
-
714
- try {
715
- for (var _iterator5 = (0, _private_utils.entries)(record.cellValuesByFieldId)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
716
- var _step5$value = (0, _slicedToArray2.default)(_step5.value, 2),
717
- fieldId = _step5$value[0],
718
- cellValue = _step5$value[1];
719
-
720
- if (_recordStore3.areCellValuesLoadedForFieldId(fieldId)) {
721
- filteredCellValuesByFieldId[fieldId] = cellValue;
722
- }
723
- }
724
- } catch (err) {
725
- _didIteratorError5 = true;
726
- _iteratorError5 = err;
727
- } finally {
728
- try {
729
- if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
730
- _iterator5.return();
731
- }
732
- } finally {
733
- if (_didIteratorError5) {
734
- throw _iteratorError5;
735
- }
736
- }
737
- }
738
-
739
- return {
740
- path: ['tablesById', _tableId7, 'recordsById', record.id],
741
- value: {
742
- id: record.id,
743
- cellValuesByFieldId: filteredCellValuesByFieldId,
744
- commentCount: 0,
745
- createdTime: new Date().toJSON()
746
- }
747
- };
748
- }), ...this._base.getTableById(_tableId7).views.flatMap(view => {
749
- var viewDataStore = _recordStore3.getViewDataStore(view.id);
750
-
751
- if (!viewDataStore.isDataLoaded) {
752
- return [];
753
- }
754
-
755
- return viewDataStore.__generateChangesForParentTableAddMultipleRecords(_records2.map(record => record.id));
756
- })];
757
- }
758
- // The following branch is unreachable because this method's only
759
- // call site is preceded by an explicit guard for this condition.
760
- // istanbul ignore next
761
-
762
- case _mutations.MutationTypes.SET_MULTIPLE_GLOBAL_CONFIG_PATHS:
763
- {
764
- throw (0, _error_utils.spawnError)('attempting to generate model updates for SET_MULTIPLE_GLOBAL_CONFIG_PATH');
765
- }
766
-
767
- case _mutations.MutationTypes.CREATE_SINGLE_FIELD:
768
- case _mutations.MutationTypes.UPDATE_SINGLE_FIELD_CONFIG:
769
- case _mutations.MutationTypes.UPDATE_VIEW_METADATA:
770
- case _mutations.MutationTypes.CREATE_SINGLE_TABLE:
771
- {
772
- // No optimistic updates for field, view metadata, or table mutations.
773
- return [];
774
- }
775
- // The following branch is unreachable because this method's only
776
- // call site is preceded by an explicit guard for this condition.
777
- // istanbul ignore next
778
-
779
- default:
780
- throw (0, _error_utils.spawnUnknownSwitchCaseError)('mutation type', mutation, 'type');
781
- }
782
- }
783
675
  }]);
784
676
  return Mutations;
785
677
  }();