mutation.esm.js 8.2 KB

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