import { defaultLogger } from './logger.mjs'; import { notifyManager } from './notifyManager.mjs'; import { Removable } from './removable.mjs'; import { createRetryer, canFetch } from './retryer.mjs'; // CLASS class Mutation extends Removable { constructor(config) { super(); this.defaultOptions = config.defaultOptions; this.mutationId = config.mutationId; this.mutationCache = config.mutationCache; this.logger = config.logger || defaultLogger; this.observers = []; this.state = config.state || getDefaultState(); this.setOptions(config.options); this.scheduleGc(); } setOptions(options) { this.options = { ...this.defaultOptions, ...options }; this.updateCacheTime(this.options.cacheTime); } get meta() { return this.options.meta; } setState(state) { this.dispatch({ type: 'setState', state }); } addObserver(observer) { if (!this.observers.includes(observer)) { this.observers.push(observer); // Stop the mutation from being garbage collected this.clearGcTimeout(); this.mutationCache.notify({ type: 'observerAdded', mutation: this, observer }); } } removeObserver(observer) { this.observers = this.observers.filter(x => x !== observer); this.scheduleGc(); this.mutationCache.notify({ type: 'observerRemoved', mutation: this, observer }); } optionalRemove() { if (!this.observers.length) { if (this.state.status === 'loading') { this.scheduleGc(); } else { this.mutationCache.remove(this); } } } continue() { var _this$retryer$continu, _this$retryer; return (_this$retryer$continu = (_this$retryer = this.retryer) == null ? void 0 : _this$retryer.continue()) != null ? _this$retryer$continu : this.execute(); } async execute() { const executeMutation = () => { var _this$options$retry; this.retryer = createRetryer({ fn: () => { if (!this.options.mutationFn) { return Promise.reject('No mutationFn found'); } return this.options.mutationFn(this.state.variables); }, onFail: (failureCount, error) => { this.dispatch({ type: 'failed', failureCount, error }); }, onPause: () => { this.dispatch({ type: 'pause' }); }, onContinue: () => { this.dispatch({ type: 'continue' }); }, retry: (_this$options$retry = this.options.retry) != null ? _this$options$retry : 0, retryDelay: this.options.retryDelay, networkMode: this.options.networkMode }); return this.retryer.promise; }; const restored = this.state.status === 'loading'; try { var _this$mutationCache$c3, _this$mutationCache$c4, _this$options$onSucce, _this$options2, _this$mutationCache$c5, _this$mutationCache$c6, _this$options$onSettl, _this$options3; if (!restored) { var _this$mutationCache$c, _this$mutationCache$c2, _this$options$onMutat, _this$options; this.dispatch({ type: 'loading', variables: this.options.variables }); // Notify cache callback 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)); const context = await ((_this$options$onMutat = (_this$options = this.options).onMutate) == null ? void 0 : _this$options$onMutat.call(_this$options, this.state.variables)); if (context !== this.state.context) { this.dispatch({ type: 'loading', context, variables: this.state.variables }); } } const data = await executeMutation(); // Notify cache callback 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)); 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 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)); 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)); this.dispatch({ type: 'success', data }); return data; } catch (error) { try { var _this$mutationCache$c7, _this$mutationCache$c8, _this$options$onError, _this$options4, _this$mutationCache$c9, _this$mutationCache$c10, _this$options$onSettl2, _this$options5; // Notify cache callback 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)); if (process.env.NODE_ENV !== 'production') { this.logger.error(error); } 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 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)); 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)); throw error; } finally { this.dispatch({ type: 'error', error: error }); } } } dispatch(action) { const reducer = state => { switch (action.type) { case 'failed': return { ...state, failureCount: action.failureCount, failureReason: action.error }; case 'pause': return { ...state, isPaused: true }; case 'continue': return { ...state, isPaused: false }; case 'loading': return { ...state, context: action.context, data: undefined, failureCount: 0, failureReason: null, error: null, isPaused: !canFetch(this.options.networkMode), status: 'loading', variables: action.variables }; case 'success': return { ...state, data: action.data, failureCount: 0, failureReason: null, error: null, status: 'success', isPaused: false }; case 'error': return { ...state, data: undefined, error: action.error, failureCount: state.failureCount + 1, failureReason: action.error, isPaused: false, status: 'error' }; case 'setState': return { ...state, ...action.state }; } }; this.state = reducer(this.state); notifyManager.batch(() => { this.observers.forEach(observer => { observer.onMutationUpdate(action); }); this.mutationCache.notify({ mutation: this, type: 'updated', action }); }); } } function getDefaultState() { return { context: undefined, data: undefined, error: null, failureCount: 0, failureReason: null, isPaused: false, status: 'idle', variables: undefined }; } export { Mutation, getDefaultState }; //# sourceMappingURL=mutation.mjs.map