relay-runtime 9.0.0 → 9.1.0

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 (111) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +34 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/index.js +1 -1
  5. package/index.js.flow +314 -0
  6. package/lib/handlers/connection/ConnectionHandler.js +1 -3
  7. package/lib/index.js +1 -2
  8. package/lib/mutations/RelayDeclarativeMutationConfig.js +22 -45
  9. package/lib/mutations/RelayRecordProxy.js +1 -3
  10. package/lib/mutations/RelayRecordSourceMutator.js +1 -3
  11. package/lib/mutations/RelayRecordSourceProxy.js +1 -3
  12. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -3
  13. package/lib/mutations/commitMutation.js +2 -0
  14. package/lib/mutations/validateMutation.js +13 -4
  15. package/lib/network/RelayObservable.js +9 -9
  16. package/lib/network/RelayQueryResponseCache.js +8 -6
  17. package/lib/query/fetchQueryInternal.js +1 -8
  18. package/lib/store/DataChecker.js +23 -51
  19. package/lib/store/RelayConcreteVariables.js +6 -2
  20. package/lib/store/RelayModernEnvironment.js +30 -12
  21. package/lib/store/RelayModernFragmentSpecResolver.js +9 -13
  22. package/lib/store/RelayModernQueryExecutor.js +73 -37
  23. package/lib/store/RelayModernRecord.js +14 -9
  24. package/lib/store/RelayModernStore.js +107 -70
  25. package/lib/store/RelayOperationTracker.js +35 -78
  26. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  27. package/lib/store/RelayPublishQueue.js +1 -3
  28. package/lib/store/RelayReader.js +1 -3
  29. package/lib/store/RelayRecordSource.js +1 -3
  30. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  31. package/lib/store/RelayReferenceMarker.js +2 -6
  32. package/lib/store/RelayResponseNormalizer.js +9 -10
  33. package/lib/store/StoreInspector.js +7 -5
  34. package/lib/store/normalizeRelayPayload.js +6 -2
  35. package/lib/subscription/requestSubscription.js +4 -2
  36. package/lib/util/RelayFeatureFlags.js +1 -1
  37. package/lib/util/RelayReplaySubject.js +1 -3
  38. package/lib/util/createPayloadFor3DField.js +7 -2
  39. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  40. package/mutations/RelayRecordProxy.js.flow +165 -0
  41. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  42. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  43. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  44. package/mutations/applyOptimisticMutation.js.flow +76 -0
  45. package/mutations/commitLocalUpdate.js.flow +24 -0
  46. package/mutations/commitMutation.js.flow +184 -0
  47. package/mutations/validateMutation.js.flow +211 -0
  48. package/network/ConvertToExecuteFunction.js.flow +49 -0
  49. package/network/RelayNetwork.js.flow +84 -0
  50. package/network/RelayNetworkTypes.js.flow +123 -0
  51. package/network/RelayObservable.js.flow +634 -0
  52. package/network/RelayQueryResponseCache.js.flow +111 -0
  53. package/package.json +1 -1
  54. package/query/GraphQLTag.js.flow +166 -0
  55. package/query/fetchQuery.js.flow +47 -0
  56. package/query/fetchQueryInternal.js.flow +349 -0
  57. package/relay-runtime.js +2 -2
  58. package/relay-runtime.min.js +2 -2
  59. package/store/ClientID.js.flow +43 -0
  60. package/store/DataChecker.js.flow +426 -0
  61. package/store/RelayConcreteVariables.js.flow +96 -0
  62. package/store/RelayModernEnvironment.js.flow +526 -0
  63. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  64. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  65. package/store/RelayModernQueryExecutor.js.flow +1327 -0
  66. package/store/RelayModernRecord.js.flow +403 -0
  67. package/store/RelayModernSelector.js.flow +444 -0
  68. package/store/RelayModernStore.js.flow +757 -0
  69. package/store/RelayOperationTracker.js.flow +164 -0
  70. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  71. package/store/RelayPublishQueue.js.flow +401 -0
  72. package/store/RelayReader.js.flow +376 -0
  73. package/store/RelayRecordSource.js.flow +29 -0
  74. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  75. package/store/RelayRecordState.js.flow +37 -0
  76. package/store/RelayReferenceMarker.js.flow +236 -0
  77. package/store/RelayResponseNormalizer.js.flow +556 -0
  78. package/store/RelayStoreTypes.js.flow +873 -0
  79. package/store/RelayStoreUtils.js.flow +218 -0
  80. package/store/StoreInspector.js.flow +173 -0
  81. package/store/ViewerPattern.js.flow +26 -0
  82. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  83. package/store/createFragmentSpecResolver.js.flow +55 -0
  84. package/store/createRelayContext.js.flow +44 -0
  85. package/store/defaultGetDataID.js.flow +27 -0
  86. package/store/hasOverlappingIDs.js.flow +34 -0
  87. package/store/isRelayModernEnvironment.js.flow +27 -0
  88. package/store/normalizeRelayPayload.js.flow +51 -0
  89. package/store/readInlineData.js.flow +75 -0
  90. package/subscription/requestSubscription.js.flow +100 -0
  91. package/util/JSResourceTypes.flow.js.flow +20 -0
  92. package/util/NormalizationNode.js.flow +191 -0
  93. package/util/ReaderNode.js.flow +208 -0
  94. package/util/RelayConcreteNode.js.flow +80 -0
  95. package/util/RelayDefaultHandleKey.js.flow +17 -0
  96. package/util/RelayError.js.flow +33 -0
  97. package/util/RelayFeatureFlags.js.flow +30 -0
  98. package/util/RelayProfiler.js.flow +284 -0
  99. package/util/RelayReplaySubject.js.flow +134 -0
  100. package/util/RelayRuntimeTypes.js.flow +70 -0
  101. package/util/createPayloadFor3DField.js.flow +43 -0
  102. package/util/deepFreeze.js.flow +36 -0
  103. package/util/generateID.js.flow +21 -0
  104. package/util/getFragmentIdentifier.js.flow +52 -0
  105. package/util/getRelayHandleKey.js.flow +41 -0
  106. package/util/getRequestIdentifier.js.flow +41 -0
  107. package/util/isPromise.js.flow +21 -0
  108. package/util/isScalarAndEqual.js.flow +26 -0
  109. package/util/recycleNodesInto.js.flow +80 -0
  110. package/util/resolveImmediate.js.flow +30 -0
  111. package/util/stableCopy.js.flow +35 -0
@@ -10,6 +10,12 @@
10
10
  // flowlint ambiguous-object-type:error
11
11
  'use strict';
12
12
 
13
+ function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
14
+
15
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
+
17
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
18
+
13
19
  var RelayRecordState = require('./RelayRecordState');
14
20
 
15
21
  var EXISTENT = RelayRecordState.EXISTENT,
@@ -20,9 +26,7 @@ var EXISTENT = RelayRecordState.EXISTENT,
20
26
  * `RelayStoreTypes`) that holds all records in memory (JS Map).
21
27
  */
22
28
 
23
- var RelayMapRecordSourceMapImpl =
24
- /*#__PURE__*/
25
- function () {
29
+ var RelayMapRecordSourceMapImpl = /*#__PURE__*/function () {
26
30
  function RelayMapRecordSourceMapImpl(records) {
27
31
  var _this = this;
28
32
 
@@ -79,30 +83,21 @@ function () {
79
83
 
80
84
  _proto.toJSON = function toJSON() {
81
85
  var obj = {};
82
- var _iteratorNormalCompletion = true;
83
- var _didIteratorError = false;
84
- var _iteratorError = undefined;
86
+
87
+ var _iterator = _createForOfIteratorHelper(this._records),
88
+ _step;
85
89
 
86
90
  try {
87
- for (var _iterator = this._records[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
91
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
88
92
  var _step$value = _step.value,
89
93
  key = _step$value[0],
90
94
  value = _step$value[1];
91
95
  obj[key] = value;
92
96
  }
93
97
  } catch (err) {
94
- _didIteratorError = true;
95
- _iteratorError = err;
98
+ _iterator.e(err);
96
99
  } finally {
97
- try {
98
- if (!_iteratorNormalCompletion && _iterator["return"] != null) {
99
- _iterator["return"]();
100
- }
101
- } finally {
102
- if (_didIteratorError) {
103
- throw _iteratorError;
104
- }
105
- }
100
+ _iterator.f();
106
101
  }
107
102
 
108
103
  return obj;
@@ -46,13 +46,9 @@ function mark(recordSource, selector, references, operationLoader) {
46
46
  */
47
47
 
48
48
 
49
- var RelayReferenceMarker =
50
- /*#__PURE__*/
51
- function () {
49
+ var RelayReferenceMarker = /*#__PURE__*/function () {
52
50
  function RelayReferenceMarker(recordSource, variables, references, operationLoader) {
53
- var _operationLoader;
54
-
55
- this._operationLoader = (_operationLoader = operationLoader) !== null && _operationLoader !== void 0 ? _operationLoader : null;
51
+ this._operationLoader = operationLoader !== null && operationLoader !== void 0 ? operationLoader : null;
56
52
  this._recordSource = recordSource;
57
53
  this._references = references;
58
54
  this._variables = variables;
@@ -47,7 +47,8 @@ var _require4 = require('./RelayStoreUtils'),
47
47
  getModuleComponentKey = _require4.getModuleComponentKey,
48
48
  getModuleOperationKey = _require4.getModuleOperationKey,
49
49
  getStorageKey = _require4.getStorageKey,
50
- TYPENAME_KEY = _require4.TYPENAME_KEY;
50
+ TYPENAME_KEY = _require4.TYPENAME_KEY,
51
+ ROOT_ID = _require4.ROOT_ID;
51
52
 
52
53
  /**
53
54
  * Normalizes the results of a query and standard GraphQL response, writing the
@@ -67,12 +68,11 @@ function normalize(recordSource, selector, response, options) {
67
68
  */
68
69
 
69
70
 
70
- var RelayResponseNormalizer =
71
- /*#__PURE__*/
72
- function () {
71
+ var RelayResponseNormalizer = /*#__PURE__*/function () {
73
72
  function RelayResponseNormalizer(recordSource, variables, options) {
74
73
  this._getDataId = options.getDataID;
75
74
  this._handleFieldPayloads = [];
75
+ this._treatMissingFieldsAsNull = options.treatMissingFieldsAsNull;
76
76
  this._incrementalPlaceholders = [];
77
77
  this._isClientExtension = false;
78
78
  this._moduleImportPayloads = [];
@@ -240,16 +240,14 @@ function () {
240
240
  };
241
241
 
242
242
  _proto._normalizeModuleImport = function _normalizeModuleImport(parent, moduleImport, record, data) {
243
- var _componentReference, _operationReference;
244
-
245
243
  !(typeof data === 'object' && data) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected data for @module to be an object.') : invariant(false) : void 0;
246
244
  var typeName = RelayModernRecord.getType(record);
247
245
  var componentKey = getModuleComponentKey(moduleImport.documentName);
248
246
  var componentReference = data[componentKey];
249
- RelayModernRecord.setValue(record, componentKey, (_componentReference = componentReference) !== null && _componentReference !== void 0 ? _componentReference : null);
247
+ RelayModernRecord.setValue(record, componentKey, componentReference !== null && componentReference !== void 0 ? componentReference : null);
250
248
  var operationKey = getModuleOperationKey(moduleImport.documentName);
251
249
  var operationReference = data[operationKey];
252
- RelayModernRecord.setValue(record, operationKey, (_operationReference = operationReference) !== null && _operationReference !== void 0 ? _operationReference : null);
250
+ RelayModernRecord.setValue(record, operationKey, operationReference !== null && operationReference !== void 0 ? operationReference : null);
253
251
 
254
252
  if (operationReference != null) {
255
253
  this._moduleImportPayloads.push({
@@ -270,7 +268,7 @@ function () {
270
268
  var fieldValue = data[responseKey];
271
269
 
272
270
  if (fieldValue == null) {
273
- if (fieldValue === undefined) {
271
+ if (!this._treatMissingFieldsAsNull && fieldValue === undefined) {
274
272
  // Fields that are missing in the response are not set on the record.
275
273
  // There are three main cases where this can occur:
276
274
  // - Inside a client extension: the server will not generally return
@@ -413,7 +411,8 @@ function () {
413
411
  var _field$concreteType3;
414
412
 
415
413
  var typeName = (_field$concreteType3 = field.concreteType) !== null && _field$concreteType3 !== void 0 ? _field$concreteType3 : this._getRecordType(payload);
416
- process.env.NODE_ENV !== "production" ? warning(isClientID(RelayModernRecord.getDataID(record)) || RelayModernRecord.getType(record) === typeName, 'RelayResponseNormalizer: Invalid record `%s`. Expected %s to be ' + 'consistent, but the record was assigned conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', RelayModernRecord.getDataID(record), TYPENAME_KEY, RelayModernRecord.getType(record), typeName) : void 0;
414
+ var dataID = RelayModernRecord.getDataID(record);
415
+ process.env.NODE_ENV !== "production" ? warning(isClientID(dataID) && dataID !== ROOT_ID || RelayModernRecord.getType(record) === typeName, 'RelayResponseNormalizer: Invalid record `%s`. Expected %s to be ' + 'consistent, but the record was assigned conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', dataID, TYPENAME_KEY, RelayModernRecord.getType(record), typeName) : void 0;
417
416
  };
418
417
 
419
418
  return RelayResponseNormalizer;
@@ -13,10 +13,14 @@
13
13
 
14
14
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
15
 
16
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
16
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
17
 
18
18
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
19
 
20
+ 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; }
21
+
22
+ 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; }
23
+
20
24
  var inspect = function inspect() {};
21
25
 
22
26
  if (process.env.NODE_ENV !== "production") {
@@ -134,7 +138,7 @@ if (process.env.NODE_ENV !== "production") {
134
138
  return record;
135
139
  }
136
140
 
137
- return new Proxy((0, _objectSpread2["default"])({}, record), {
141
+ return new Proxy(_objectSpread({}, record), {
138
142
  get: function get(target, prop) {
139
143
  var value = target[prop];
140
144
 
@@ -163,10 +167,8 @@ if (process.env.NODE_ENV !== "production") {
163
167
  };
164
168
 
165
169
  inspect = function inspect(environment, dataID) {
166
- var _dataID;
167
-
168
170
  installDevtoolFormatters();
169
- return getWrappedRecord(environment.getStore().getSource(), (_dataID = dataID) !== null && _dataID !== void 0 ? _dataID : 'client:root');
171
+ return getWrappedRecord(environment.getStore().getSource(), dataID !== null && dataID !== void 0 ? dataID : 'client:root');
170
172
  };
171
173
  }
172
174
 
@@ -12,7 +12,11 @@
12
12
 
13
13
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
14
14
 
15
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
15
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
+
17
+ 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; }
18
+
19
+ 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; }
16
20
 
17
21
  var RelayModernRecord = require('./RelayModernRecord');
18
22
 
@@ -27,7 +31,7 @@ function normalizeRelayPayload(selector, payload, errors, options) {
27
31
  var source = RelayRecordSource.create();
28
32
  source.set(selector.dataID, RelayModernRecord.create(selector.dataID, ROOT_TYPE));
29
33
  var relayPayload = RelayResponseNormalizer.normalize(source, selector, payload, options);
30
- return (0, _objectSpread2["default"])({}, relayPayload, {
34
+ return _objectSpread({}, relayPayload, {
31
35
  errors: errors
32
36
  });
33
37
  }
@@ -31,7 +31,8 @@ function requestSubscription(environment, config) {
31
31
  onCompleted = config.onCompleted,
32
32
  onError = config.onError,
33
33
  onNext = config.onNext,
34
- variables = config.variables;
34
+ variables = config.variables,
35
+ cacheConfig = config.cacheConfig;
35
36
  var operation = createOperationDescriptor(subscription, variables);
36
37
  process.env.NODE_ENV !== "production" ? warning(!(config.updater && configs), 'requestSubscription: Expected only one of `updater` and `configs` to be provided') : void 0;
37
38
 
@@ -42,7 +43,8 @@ function requestSubscription(environment, config) {
42
43
 
43
44
  var sub = environment.execute({
44
45
  operation: operation,
45
- updater: updater
46
+ updater: updater,
47
+ cacheConfig: cacheConfig
46
48
  }).map(function () {
47
49
  var data = environment.lookup(operation.fragment).data; // $FlowFixMe
48
50
 
@@ -14,7 +14,7 @@ var RelayFeatureFlags = {
14
14
  // T45504512: new connection model
15
15
  ENABLE_VARIABLE_CONNECTION_KEY: false,
16
16
  ENABLE_PARTIAL_RENDERING_DEFAULT: false,
17
- ENABLE_RELAY_CONTAINERS_SUSPENSE: true,
17
+ ENABLE_RELAY_CONTAINERS_SUSPENSE: false,
18
18
  ENABLE_UNIQUE_MUTATION_ROOT: true
19
19
  };
20
20
  module.exports = RelayFeatureFlags;
@@ -24,9 +24,7 @@ var invariant = require("fbjs/lib/invariant");
24
24
  * Records events provided and synchronously plays them back to new subscribers,
25
25
  * as well as forwarding new asynchronous events.
26
26
  */
27
- var RelayReplaySubject =
28
- /*#__PURE__*/
29
- function () {
27
+ var RelayReplaySubject = /*#__PURE__*/function () {
30
28
  function RelayReplaySubject() {
31
29
  var _this = this;
32
30
 
@@ -13,14 +13,19 @@
13
13
 
14
14
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
15
 
16
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
16
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
+
18
+ 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; }
19
+
20
+ 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; }
17
21
 
18
22
  var _require = require('../store/RelayStoreUtils'),
19
23
  getModuleComponentKey = _require.getModuleComponentKey,
20
24
  getModuleOperationKey = _require.getModuleOperationKey;
21
25
 
22
26
  function createPayloadFor3DField(name, operation, component, response) {
23
- var data = (0, _objectSpread2["default"])({}, response);
27
+ var data = _objectSpread({}, response);
28
+
24
29
  data[getModuleComponentKey(name)] = component;
25
30
  data[getModuleOperationKey(name)] = operation;
26
31
  return data;
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const ConnectionHandler = require('../handlers/connection/ConnectionHandler');
16
+
17
+ const warning = require('warning');
18
+
19
+ import type {
20
+ RecordSourceSelectorProxy,
21
+ SelectorData,
22
+ SelectorStoreUpdater,
23
+ } from '../store/RelayStoreTypes';
24
+ import type {ConcreteRequest} from '../util/RelayConcreteNode';
25
+ import type {Variables} from '../util/RelayRuntimeTypes';
26
+
27
+ const MutationTypes = Object.freeze({
28
+ RANGE_ADD: 'RANGE_ADD',
29
+ RANGE_DELETE: 'RANGE_DELETE',
30
+ NODE_DELETE: 'NODE_DELETE',
31
+ });
32
+ export type MutationType = $Values<typeof MutationTypes>;
33
+
34
+ const RangeOperations = Object.freeze({
35
+ APPEND: 'append',
36
+ PREPEND: 'prepend',
37
+ });
38
+ export type RangeOperation = $Values<typeof RangeOperations>;
39
+
40
+ type RangeBehaviorsFunction = (connectionArgs: {
41
+ [name: string]: $FlowFixMe,
42
+ ...,
43
+ }) => RangeOperation;
44
+ type RangeBehaviorsObject = {[key: string]: RangeOperation, ...};
45
+ export type RangeBehaviors = RangeBehaviorsFunction | RangeBehaviorsObject;
46
+
47
+ type RangeAddConfig = {|
48
+ type: 'RANGE_ADD',
49
+ parentName?: string,
50
+ parentID?: string,
51
+ connectionInfo?: Array<{|
52
+ key: string,
53
+ filters?: Variables,
54
+ rangeBehavior: string,
55
+ |}>,
56
+ connectionName?: string,
57
+ edgeName: string,
58
+ rangeBehaviors?: RangeBehaviors,
59
+ |};
60
+
61
+ type RangeDeleteConfig = {|
62
+ type: 'RANGE_DELETE',
63
+ parentName?: string,
64
+ parentID?: string,
65
+ connectionKeys?: Array<{|
66
+ key: string,
67
+ filters?: Variables,
68
+ |}>,
69
+ connectionName?: string,
70
+ deletedIDFieldName: string | Array<string>,
71
+ pathToConnection: Array<string>,
72
+ |};
73
+
74
+ type NodeDeleteConfig = {|
75
+ type: 'NODE_DELETE',
76
+ parentName?: string,
77
+ parentID?: string,
78
+ connectionName?: string,
79
+ deletedIDFieldName: string,
80
+ |};
81
+
82
+ export type DeclarativeMutationConfig =
83
+ | RangeAddConfig
84
+ | RangeDeleteConfig
85
+ | NodeDeleteConfig;
86
+
87
+ function convert(
88
+ configs: Array<DeclarativeMutationConfig>,
89
+ request: ConcreteRequest,
90
+ optimisticUpdater?: ?SelectorStoreUpdater,
91
+ updater?: ?SelectorStoreUpdater,
92
+ ): {
93
+ optimisticUpdater: SelectorStoreUpdater,
94
+ updater: SelectorStoreUpdater,
95
+ ...
96
+ } {
97
+ const configOptimisticUpdates = optimisticUpdater ? [optimisticUpdater] : [];
98
+ const configUpdates = updater ? [updater] : [];
99
+ configs.forEach(config => {
100
+ switch (config.type) {
101
+ case 'NODE_DELETE':
102
+ const nodeDeleteResult = nodeDelete(config, request);
103
+ if (nodeDeleteResult) {
104
+ configOptimisticUpdates.push(nodeDeleteResult);
105
+ configUpdates.push(nodeDeleteResult);
106
+ }
107
+ break;
108
+ case 'RANGE_ADD':
109
+ const rangeAddResult = rangeAdd(config, request);
110
+ if (rangeAddResult) {
111
+ configOptimisticUpdates.push(rangeAddResult);
112
+ configUpdates.push(rangeAddResult);
113
+ }
114
+ break;
115
+ case 'RANGE_DELETE':
116
+ const rangeDeleteResult = rangeDelete(config, request);
117
+ if (rangeDeleteResult) {
118
+ configOptimisticUpdates.push(rangeDeleteResult);
119
+ configUpdates.push(rangeDeleteResult);
120
+ }
121
+ break;
122
+ }
123
+ });
124
+ return {
125
+ optimisticUpdater: (
126
+ store: RecordSourceSelectorProxy,
127
+ data: ?SelectorData,
128
+ ) => {
129
+ configOptimisticUpdates.forEach(eachOptimisticUpdater => {
130
+ eachOptimisticUpdater(store, data);
131
+ });
132
+ },
133
+ updater: (store: RecordSourceSelectorProxy, data: ?SelectorData) => {
134
+ configUpdates.forEach(eachUpdater => {
135
+ eachUpdater(store, data);
136
+ });
137
+ },
138
+ };
139
+ }
140
+
141
+ function nodeDelete(
142
+ config: NodeDeleteConfig,
143
+ request: ConcreteRequest,
144
+ ): ?SelectorStoreUpdater {
145
+ const {deletedIDFieldName} = config;
146
+ const rootField = getRootField(request);
147
+ if (!rootField) {
148
+ return null;
149
+ }
150
+ return (store: RecordSourceSelectorProxy, data: ?SelectorData) => {
151
+ const payload = store.getRootField(rootField);
152
+ if (!payload) {
153
+ return;
154
+ }
155
+ const deleteID = payload.getValue(deletedIDFieldName);
156
+ const deleteIDs = Array.isArray(deleteID) ? deleteID : [deleteID];
157
+ deleteIDs.forEach(id => {
158
+ if (id && typeof id === 'string') {
159
+ store.delete(id);
160
+ }
161
+ });
162
+ };
163
+ }
164
+
165
+ function rangeAdd(
166
+ config: RangeAddConfig,
167
+ request: ConcreteRequest,
168
+ ): ?SelectorStoreUpdater {
169
+ const {parentID, connectionInfo, edgeName} = config;
170
+ if (!parentID) {
171
+ warning(
172
+ false,
173
+ 'RelayDeclarativeMutationConfig: For mutation config RANGE_ADD ' +
174
+ 'to work you must include a parentID',
175
+ );
176
+ return null;
177
+ }
178
+ const rootField = getRootField(request);
179
+ if (!connectionInfo || !rootField) {
180
+ return null;
181
+ }
182
+ return (store: RecordSourceSelectorProxy, data: ?SelectorData) => {
183
+ const parent = store.get(parentID);
184
+ if (!parent) {
185
+ return;
186
+ }
187
+ const payload = store.getRootField(rootField);
188
+ if (!payload) {
189
+ return;
190
+ }
191
+ const serverEdge = payload.getLinkedRecord(edgeName);
192
+ for (const info of connectionInfo) {
193
+ if (!serverEdge) {
194
+ continue;
195
+ }
196
+ const connection = ConnectionHandler.getConnection(
197
+ parent,
198
+ info.key,
199
+ info.filters,
200
+ );
201
+ if (!connection) {
202
+ continue;
203
+ }
204
+ const clientEdge = ConnectionHandler.buildConnectionEdge(
205
+ store,
206
+ connection,
207
+ serverEdge,
208
+ );
209
+ if (!clientEdge) {
210
+ continue;
211
+ }
212
+ switch (info.rangeBehavior) {
213
+ case 'append':
214
+ ConnectionHandler.insertEdgeAfter(connection, clientEdge);
215
+ break;
216
+ case 'prepend':
217
+ ConnectionHandler.insertEdgeBefore(connection, clientEdge);
218
+ break;
219
+ default:
220
+ warning(
221
+ false,
222
+ 'RelayDeclarativeMutationConfig: RANGE_ADD range behavior `%s` ' +
223
+ 'will not work as expected in RelayModern, supported range ' +
224
+ "behaviors are 'append', 'prepend'.",
225
+ info.rangeBehavior,
226
+ );
227
+ break;
228
+ }
229
+ }
230
+ };
231
+ }
232
+
233
+ function rangeDelete(
234
+ config: RangeDeleteConfig,
235
+ request: ConcreteRequest,
236
+ ): ?SelectorStoreUpdater {
237
+ const {
238
+ parentID,
239
+ connectionKeys,
240
+ pathToConnection,
241
+ deletedIDFieldName,
242
+ } = config;
243
+ if (!parentID) {
244
+ warning(
245
+ false,
246
+ 'RelayDeclarativeMutationConfig: For mutation config RANGE_DELETE ' +
247
+ 'to work you must include a parentID',
248
+ );
249
+ return null;
250
+ }
251
+ const rootField = getRootField(request);
252
+ if (!rootField) {
253
+ return null;
254
+ }
255
+ return (store: RecordSourceSelectorProxy, data: ?SelectorData) => {
256
+ if (!data) {
257
+ return;
258
+ }
259
+ const deleteIDs = [];
260
+ let deletedIDField = data[rootField];
261
+ if (deletedIDField && Array.isArray(deletedIDFieldName)) {
262
+ for (const eachField of deletedIDFieldName) {
263
+ if (deletedIDField && typeof deletedIDField === 'object') {
264
+ deletedIDField = deletedIDField[eachField];
265
+ }
266
+ }
267
+ if (Array.isArray(deletedIDField)) {
268
+ deletedIDField.forEach(idObject => {
269
+ if (
270
+ idObject &&
271
+ idObject.id &&
272
+ typeof idObject === 'object' &&
273
+ typeof idObject.id === 'string'
274
+ ) {
275
+ deleteIDs.push(idObject.id);
276
+ }
277
+ });
278
+ } else if (
279
+ deletedIDField &&
280
+ deletedIDField.id &&
281
+ typeof deletedIDField.id === 'string'
282
+ ) {
283
+ deleteIDs.push(deletedIDField.id);
284
+ }
285
+ } else if (
286
+ deletedIDField &&
287
+ typeof deletedIDFieldName === 'string' &&
288
+ typeof deletedIDField === 'object'
289
+ ) {
290
+ deletedIDField = deletedIDField[deletedIDFieldName];
291
+ if (typeof deletedIDField === 'string') {
292
+ deleteIDs.push(deletedIDField);
293
+ } else if (Array.isArray(deletedIDField)) {
294
+ deletedIDField.forEach(id => {
295
+ if (typeof id === 'string') {
296
+ deleteIDs.push(id);
297
+ }
298
+ });
299
+ }
300
+ }
301
+ deleteNode(parentID, connectionKeys, pathToConnection, store, deleteIDs);
302
+ };
303
+ }
304
+
305
+ function deleteNode(
306
+ parentID: string,
307
+ connectionKeys: ?Array<{|
308
+ key: string,
309
+ filters?: Variables,
310
+ |}>,
311
+ pathToConnection: Array<string>,
312
+ store: RecordSourceSelectorProxy,
313
+ deleteIDs: Array<string>,
314
+ ): void {
315
+ warning(
316
+ connectionKeys != null,
317
+ 'RelayDeclarativeMutationConfig: RANGE_DELETE must provide a ' +
318
+ 'connectionKeys',
319
+ );
320
+ const parent = store.get(parentID);
321
+ if (!parent) {
322
+ return;
323
+ }
324
+ if (pathToConnection.length < 2) {
325
+ warning(
326
+ false,
327
+ 'RelayDeclarativeMutationConfig: RANGE_DELETE ' +
328
+ 'pathToConnection must include at least parent and connection',
329
+ );
330
+ return;
331
+ }
332
+ let recordProxy = parent;
333
+ for (let i = 1; i < pathToConnection.length - 1; i++) {
334
+ if (recordProxy) {
335
+ recordProxy = recordProxy.getLinkedRecord(pathToConnection[i]);
336
+ }
337
+ }
338
+ // Should never enter loop except edge cases
339
+ if (!connectionKeys || !recordProxy) {
340
+ warning(
341
+ false,
342
+ 'RelayDeclarativeMutationConfig: RANGE_DELETE ' +
343
+ 'pathToConnection is incorrect. Unable to find connection with ' +
344
+ 'parentID: %s and path: %s',
345
+ parentID,
346
+ pathToConnection.toString(),
347
+ );
348
+ return;
349
+ }
350
+ for (const key of connectionKeys) {
351
+ const connection = ConnectionHandler.getConnection(
352
+ recordProxy,
353
+ key.key,
354
+ key.filters,
355
+ );
356
+ if (connection) {
357
+ deleteIDs.forEach(deleteID => {
358
+ ConnectionHandler.deleteNode(connection, deleteID);
359
+ });
360
+ }
361
+ }
362
+ }
363
+
364
+ function getRootField(request: ConcreteRequest): ?string {
365
+ if (
366
+ request.fragment.selections &&
367
+ request.fragment.selections.length > 0 &&
368
+ request.fragment.selections[0].kind === 'LinkedField'
369
+ ) {
370
+ return request.fragment.selections[0].name;
371
+ }
372
+ return null;
373
+ }
374
+
375
+ module.exports = {
376
+ MutationTypes,
377
+ RangeOperations,
378
+
379
+ convert,
380
+ };