mutation.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var logger = require('./logger');
  4. var notifyManager = require('./notifyManager.js');
  5. var removable = require('./removable.js');
  6. var retryer = require('./retryer.js');
  7. // CLASS
  8. class Mutation extends removable.Removable {
  9. constructor(config) {
  10. super();
  11. this.defaultOptions = config.defaultOptions;
  12. this.mutationId = config.mutationId;
  13. this.mutationCache = config.mutationCache;
  14. this.logger = config.logger || logger.defaultLogger;
  15. this.observers = [];
  16. this.state = config.state || getDefaultState();
  17. this.setOptions(config.options);
  18. this.scheduleGc();
  19. }
  20. setOptions(options) {
  21. this.options = { ...this.defaultOptions,
  22. ...options
  23. };
  24. this.updateCacheTime(this.options.cacheTime);
  25. }
  26. get meta() {
  27. return this.options.meta;
  28. }
  29. setState(state) {
  30. this.dispatch({
  31. type: 'setState',
  32. state
  33. });
  34. }
  35. addObserver(observer) {
  36. if (!this.observers.includes(observer)) {
  37. this.observers.push(observer); // Stop the mutation from being garbage collected
  38. this.clearGcTimeout();
  39. this.mutationCache.notify({
  40. type: 'observerAdded',
  41. mutation: this,
  42. observer
  43. });
  44. }
  45. }
  46. removeObserver(observer) {
  47. this.observers = this.observers.filter(x => x !== observer);
  48. this.scheduleGc();
  49. this.mutationCache.notify({
  50. type: 'observerRemoved',
  51. mutation: this,
  52. observer
  53. });
  54. }
  55. optionalRemove() {
  56. if (!this.observers.length) {
  57. if (this.state.status === 'loading') {
  58. this.scheduleGc();
  59. } else {
  60. this.mutationCache.remove(this);
  61. }
  62. }
  63. }
  64. continue() {
  65. var _this$retryer$continu, _this$retryer;
  66. return (_this$retryer$continu = (_this$retryer = this.retryer) == null ? void 0 : _this$retryer.continue()) != null ? _this$retryer$continu : this.execute();
  67. }
  68. async execute() {
  69. const executeMutation = () => {
  70. var _this$options$retry;
  71. this.retryer = retryer.createRetryer({
  72. fn: () => {
  73. if (!this.options.mutationFn) {
  74. return Promise.reject('No mutationFn found');
  75. }
  76. return this.options.mutationFn(this.state.variables);
  77. },
  78. onFail: (failureCount, error) => {
  79. this.dispatch({
  80. type: 'failed',
  81. failureCount,
  82. error
  83. });
  84. },
  85. onPause: () => {
  86. this.dispatch({
  87. type: 'pause'
  88. });
  89. },
  90. onContinue: () => {
  91. this.dispatch({
  92. type: 'continue'
  93. });
  94. },
  95. retry: (_this$options$retry = this.options.retry) != null ? _this$options$retry : 0,
  96. retryDelay: this.options.retryDelay,
  97. networkMode: this.options.networkMode
  98. });
  99. return this.retryer.promise;
  100. };
  101. const restored = this.state.status === 'loading';
  102. try {
  103. var _this$mutationCache$c3, _this$mutationCache$c4, _this$options$onSucce, _this$options2, _this$mutationCache$c5, _this$mutationCache$c6, _this$options$onSettl, _this$options3;
  104. if (!restored) {
  105. var _this$mutationCache$c, _this$mutationCache$c2, _this$options$onMutat, _this$options;
  106. this.dispatch({
  107. type: 'loading',
  108. variables: this.options.variables
  109. }); // Notify cache callback
  110. await ((_this$mutationCache$c = (_this$mutationCache$c2 = this.mutationCache.config).onMutate) == null ? void 0 : _this$mutationCache$c.call(_this$mutationCache$c2, this.state.variables, this));
  111. const context = await ((_this$options$onMutat = (_this$options = this.options).onMutate) == null ? void 0 : _this$options$onMutat.call(_this$options, this.state.variables));
  112. if (context !== this.state.context) {
  113. this.dispatch({
  114. type: 'loading',
  115. context,
  116. variables: this.state.variables
  117. });
  118. }
  119. }
  120. const data = await executeMutation(); // Notify cache callback
  121. await ((_this$mutationCache$c3 = (_this$mutationCache$c4 = this.mutationCache.config).onSuccess) == null ? void 0 : _this$mutationCache$c3.call(_this$mutationCache$c4, data, this.state.variables, this.state.context, this));
  122. await ((_this$options$onSucce = (_this$options2 = this.options).onSuccess) == null ? void 0 : _this$options$onSucce.call(_this$options2, data, this.state.variables, this.state.context)); // Notify cache callback
  123. await ((_this$mutationCache$c5 = (_this$mutationCache$c6 = this.mutationCache.config).onSettled) == null ? void 0 : _this$mutationCache$c5.call(_this$mutationCache$c6, data, null, this.state.variables, this.state.context, this));
  124. await ((_this$options$onSettl = (_this$options3 = this.options).onSettled) == null ? void 0 : _this$options$onSettl.call(_this$options3, data, null, this.state.variables, this.state.context));
  125. this.dispatch({
  126. type: 'success',
  127. data
  128. });
  129. return data;
  130. } catch (error) {
  131. try {
  132. var _this$mutationCache$c7, _this$mutationCache$c8, _this$options$onError, _this$options4, _this$mutationCache$c9, _this$mutationCache$c10, _this$options$onSettl2, _this$options5;
  133. // Notify cache callback
  134. await ((_this$mutationCache$c7 = (_this$mutationCache$c8 = this.mutationCache.config).onError) == null ? void 0 : _this$mutationCache$c7.call(_this$mutationCache$c8, error, this.state.variables, this.state.context, this));
  135. if (process.env.NODE_ENV !== 'production') {
  136. this.logger.error(error);
  137. }
  138. await ((_this$options$onError = (_this$options4 = this.options).onError) == null ? void 0 : _this$options$onError.call(_this$options4, error, this.state.variables, this.state.context)); // Notify cache callback
  139. await ((_this$mutationCache$c9 = (_this$mutationCache$c10 = this.mutationCache.config).onSettled) == null ? void 0 : _this$mutationCache$c9.call(_this$mutationCache$c10, undefined, error, this.state.variables, this.state.context, this));
  140. await ((_this$options$onSettl2 = (_this$options5 = this.options).onSettled) == null ? void 0 : _this$options$onSettl2.call(_this$options5, undefined, error, this.state.variables, this.state.context));
  141. throw error;
  142. } finally {
  143. this.dispatch({
  144. type: 'error',
  145. error: error
  146. });
  147. }
  148. }
  149. }
  150. dispatch(action) {
  151. const reducer = state => {
  152. switch (action.type) {
  153. case 'failed':
  154. return { ...state,
  155. failureCount: action.failureCount,
  156. failureReason: action.error
  157. };
  158. case 'pause':
  159. return { ...state,
  160. isPaused: true
  161. };
  162. case 'continue':
  163. return { ...state,
  164. isPaused: false
  165. };
  166. case 'loading':
  167. return { ...state,
  168. context: action.context,
  169. data: undefined,
  170. failureCount: 0,
  171. failureReason: null,
  172. error: null,
  173. isPaused: !retryer.canFetch(this.options.networkMode),
  174. status: 'loading',
  175. variables: action.variables
  176. };
  177. case 'success':
  178. return { ...state,
  179. data: action.data,
  180. failureCount: 0,
  181. failureReason: null,
  182. error: null,
  183. status: 'success',
  184. isPaused: false
  185. };
  186. case 'error':
  187. return { ...state,
  188. data: undefined,
  189. error: action.error,
  190. failureCount: state.failureCount + 1,
  191. failureReason: action.error,
  192. isPaused: false,
  193. status: 'error'
  194. };
  195. case 'setState':
  196. return { ...state,
  197. ...action.state
  198. };
  199. }
  200. };
  201. this.state = reducer(this.state);
  202. notifyManager.notifyManager.batch(() => {
  203. this.observers.forEach(observer => {
  204. observer.onMutationUpdate(action);
  205. });
  206. this.mutationCache.notify({
  207. mutation: this,
  208. type: 'updated',
  209. action
  210. });
  211. });
  212. }
  213. }
  214. function getDefaultState() {
  215. return {
  216. context: undefined,
  217. data: undefined,
  218. error: null,
  219. failureCount: 0,
  220. failureReason: null,
  221. isPaused: false,
  222. status: 'idle',
  223. variables: undefined
  224. };
  225. }
  226. exports.Mutation = Mutation;
  227. exports.getDefaultState = getDefaultState;
  228. //# sourceMappingURL=mutation.js.map