Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@filerobot/utils / lib / createThunk.js
Size: Mime:
var _rejectionsErrors;
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import nanoid from './nanoid';
import handleError from './handleError';
import { isPlain } from '@reduxjs/toolkit';
var REJECTIONS = {
  CONDITION: 'Condition',
  ABORTED: 'Aborted',
  REJECTED_WITH_VALUE: 'RejectedWithValue'
};
var rejectionsErrors = (_rejectionsErrors = {}, _defineProperty(_rejectionsErrors, REJECTIONS.REJECTED_WITH_VALUE, {
  name: 'Rejected',
  message: 'Rejected with a value.'
}), _defineProperty(_rejectionsErrors, REJECTIONS.CONDITION, {
  name: 'Condition',
  message: 'Cancelled due to `condition` callback returning false.'
}), _defineProperty(_rejectionsErrors, REJECTIONS.ABORTED, {
  name: 'Abort',
  message: 'Aborted through signal of abort.'
}), _rejectionsErrors);
var getSerializedValue = function getSerializedValue(val, path, isDev) {
  if (isPlain(val)) {
    return val;
  }
  if (isDev) {
    console.warn("Non-serializable value is detected in the path (".concat(path, "), it's already has been handled and won't be passed so dismiss this warning in-case u don't care about passing this payload as it's passed as an empty object ({}):"), val);
  }
  return {};
};
var createActionCreator = function createActionCreator(type) {
  function actionCreator(payload, meta) {
    var isDev = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var error = arguments.length > 3 ? arguments[3] : undefined;
    var action = {
      type: type
    };
    if (payload !== undefined) {
      action.payload = getSerializedValue(payload, "(action.payload) of action ".concat(action.type), isDev);
    }
    if (meta !== undefined) {
      action.meta = getSerializedValue(meta, "(action.meta) of action ".concat(action.type), isDev);
    }
    if (error !== undefined) {
      action.error = getSerializedValue(error, "(action.error) of action ".concat(action.type), isDev);
    }
    return action;
  }
  actionCreator.toString = function () {
    return type;
  };
  actionCreator.type = type;
  actionCreator.match = function (action) {
    return action && action.type === type;
  };
  return actionCreator;
};

/**
 * Exact Similar to createAsyncThunk with some extra options:
 * 1. supporting both async & sync thunk functions
 * 2. added 1 more dispatched action ${actionType}/(loading, fulfilled, rejected & *final*)
 * 3. `skipDispatch` or don't provide `actionType` - incase of not wanting to dispatch any action and only need to trigger the sync/async function or manual handling for actions.
 * 4. `informError` - incase of wanting to inform the error to the user (ex. in a toast) and not dispatching any action.
 * 5. `throwRejection` - if u want to throw the error of the promise and u will handle it by catching the error by (handlePromise utility function) or .catch, then provide this `true`.
 *
 * @param {Function} dispatchedFn - the function that will be called when the thunk is dispatched
 * @param {Object}   options - the options passed for configuring the function operation
 * @param {String}    options.actionType - the action type that will be dispatched
 * @param {Function}  options.condition - the condition that will be checked before calling the dispatchedFn,
 *          -- `true`/`resolved promise` do the normal dispatch,
 *          -- `false`/`rejected promise` cancels the dispatched function implementation and return empty resolved promise.
 * @param {Boolean}   options.skipDispatch - incase of NOT wanting to dispatch any action and only need to trigger the sync/async function or manual handling for actions.
 * @param {Boolean}   options.skipPendingDispatch - it disables the dispatching of pending action, and only dispatches the fulfilled/rejected/final actions.
 * @param {Boolean}   options.informError - incase of wanting to inform the error to the user (ex. in a toast).
 * @param {Boolean}   options.throwRejection - incase of NOT wanting to handle the rejection in the return of dispatch from the function side, in that case u have to catch it urself ex. of dispatch(...).catch(...)
 *
 * @returns Function - the thunk function
 */
var createThunk = function createThunk(dispatchedFn) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var _options$actionType = options.actionType,
    actionType = _options$actionType === void 0 ? '' : _options$actionType,
    condition = options.condition,
    _options$skipDispatch = options.skipDispatch,
    skipDispatch = _options$skipDispatch === void 0 ? false : _options$skipDispatch,
    _options$skipPendingD = options.skipPendingDispatch,
    skipPendingDispatch = _options$skipPendingD === void 0 ? false : _options$skipPendingD,
    _options$informError = options.informError,
    informError = _options$informError === void 0 ? false : _options$informError;
  function payloadCreator(payload) {
    function thunkCreator(dispatch, getState, extra) {
      // if `true`, then we must handle .catch in the return of dispatch, ex. of dispatch(...).catch(...)
      var _options$throwRejecti = options.throwRejection,
        throwRejection = _options$throwRejecti === void 0 ? false : _options$throwRejecti;
      var shouldDispatch = actionType && !skipDispatch;
      var avoidPendingDispatch = skipPendingDispatch;
      var abortController = new AbortController();
      var isRequestFinished = false;
      var signal = abortController.signal;
      var abort = function abort() {
        if (isRequestFinished) {
          return;
        }
        abortController.abort();
      };
      var requestId = nanoid();

      // If the thunk function is sync then call it and return, no need to call the following logic of async function.
      // async keyword is required to be prefixed to the function to act as async thunk, otherwise it will be sync.

      // !TODO: Return back when problem with babel build if fixed on hub
      // if (dispatchedFn.constructor && dispatchedFn.constructor.name !== 'AsyncFunction' instanceof Promise) {
      var isAsync = false;
      try {
        // console.log('dispatchedFn.constructor.name: ', dispatchedFn?.constructor?.name)
        if (dispatchedFn.constructor && dispatchedFn.constructor.name === 'AsyncFunction') {
          isAsync = true;
        } else {
          isAsync = dispatchedFn() instanceof Promise;
        }
      } catch (error) {}
      if (!isAsync) {
        var thunkApi = {
          dispatch: dispatch,
          getState: getState,
          extra: extra
        };
        return dispatchedFn(payload, thunkApi);
      }
      async function asyncThunkFn() {
        var _ref2;
        var isDev = extra.filerobot.opts.dev;
        var fulfillWithValue = function fulfillWithValue(value) {
          return Promise.resolve(value);
        };
        var _rejectWithValue = function rejectWithValue(value, cbk) {
          cbk();
          return Promise.reject(value);
        };
        var replacedMetaArg = null;
        var dispatchError = function dispatchError(reason, err) {
          if (shouldDispatch) {
            var _ref;
            dispatch(payloadCreator.rejected(reason === REJECTIONS.REJECTED_WITH_VALUE ? err : undefined, {
              arg: (_ref = replacedMetaArg || payload) !== null && _ref !== void 0 ? _ref : {},
              requestId: requestId,
              requestStatus: 'rejected',
              aborted: reason === REJECTIONS.ABORTED
              // condition: reason === REJECTIONS.CONDITION
            }, isDev, rejectionsErrors[reason] || err));
          }
        };
        var thunkApi = {
          dispatch: dispatch,
          getState: getState,
          extra: extra,
          signal: signal,
          abort: abort,
          requestId: requestId,
          replaceActionsMetaArg: function replaceActionsMetaArg(metaArg) {
            replacedMetaArg = metaArg;
          },
          // sets object in the action.meta.arg properties
          skipDispatch: function skipDispatch() {
            shouldDispatch = false;
          },
          skipPendingDispatch: function skipPendingDispatch() {
            avoidPendingDispatch = true;
          },
          rejectWithValue: function rejectWithValue(value) {
            return _rejectWithValue(value, function () {
              return dispatchError(REJECTIONS.REJECTED_WITH_VALUE, value);
            });
          },
          fulfillWithValue: fulfillWithValue
        };
        if (typeof condition === 'function') {
          var result = condition(payload, thunkApi);
          if (result instanceof Promise) {
            var conditionResult = await result;
            if (!conditionResult) {
              // dispatchError(REJECTIONS.CONDITION)
              return Promise.resolve();
            }
          }
          if (!result) {
            // dispatchError(REJECTIONS.CONDITION)
            return Promise.resolve();
          }
        }

        // We moved it after calling the function, in case the function's body calls (skipDispatch function), in that case we won't dispatch the actions.
        var functionResult = dispatchedFn(payload, thunkApi);
        var properMetaArg = (_ref2 = replacedMetaArg || payload) !== null && _ref2 !== void 0 ? _ref2 : {};
        if (shouldDispatch && !avoidPendingDispatch) {
          dispatch(payloadCreator.pending(undefined, {
            arg: properMetaArg,
            requestId: requestId,
            requestStatus: 'pending'
          }, isDev));
        }
        var dispatchFinal = function dispatchFinal() {
          if (shouldDispatch) {
            dispatch(payloadCreator["final"](undefined, {
              arg: properMetaArg,
              requestId: requestId,
              requestStatus: 'final'
            }), isDev);
          }
        };
        signal.addEventListener('abort', function () {
          dispatchError(REJECTIONS.ABORTED);
          dispatchFinal();
        }, {
          once: true
        });
        var returnedPromise = functionResult.then(function (res) {
          if (shouldDispatch) {
            dispatch(payloadCreator.fulfilled(isPlain(res) ? res : {}, {
              arg: properMetaArg,
              requestId: requestId,
              requestStatus: 'fulfilled'
            }, isDev));
          }
          return res;
        })["catch"](function (err) {
          if (isDev) {
            console.error(err.stack || err.message || (err === null || err === void 0 ? void 0 : err.toString()) || err);
          }
          if (shouldDispatch) {
            var message = err.message || (err === null || err === void 0 ? void 0 : err.toString());
            dispatchError(undefined, _objectSpread({
              message: message
            }, err));
          }
          // !TODO: Check if we should make informError `true` by default instead of `false` or not.
          if (informError) {
            var _thunkApi$extra$filer;
            handleError(err, (_thunkApi$extra$filer = thunkApi.extra.filerobot) === null || _thunkApi$extra$filer === void 0 ? void 0 : _thunkApi$extra$filer.info);
          }
          if (throwRejection) {
            return Promise.reject(err);
          }
        })["finally"](function () {
          isRequestFinished = true;
          dispatchFinal();
        });
        return returnedPromise;
      }
      var returnedThunkPromise = asyncThunkFn();
      returnedThunkPromise.abort = abort;
      returnedThunkPromise.requestId = requestId;
      returnedThunkPromise.signal = signal;
      returnedThunkPromise.throwRejection = function () {
        throwRejection = true;
        return returnedThunkPromise;
      };
      return returnedThunkPromise;
    }
    return thunkCreator;
  }
  if (actionType && !skipDispatch) {
    payloadCreator.pending = createActionCreator("".concat(actionType, "/pending"));
    payloadCreator.fulfilled = createActionCreator("".concat(actionType, "/fulfilled"));
    payloadCreator.rejected = createActionCreator("".concat(actionType, "/rejected"));
    payloadCreator["final"] = createActionCreator("".concat(actionType, "/final"));
    payloadCreator.typePrefix = actionType;
  }
  return payloadCreator;
};
export default createThunk;