<commit_before>import {
  getActionPayload,
  createSuccessAction,
  createErrorAction,
  createAbortAction,
} from '../actions';
import { ABORT_REQUESTS } from '../constants';

const getRequestTypeString = requestType =>
  typeof requestType === 'function' ? requestType.toString() : requestType;

const getKeys = requests =>
  requests.map(v =>
    typeof v === 'object'
      ? getRequestTypeString(v.requestType) + v.requestKey
      : getRequestTypeString(v),
  );

const getDriver = (config, action) =>
  action.meta && action.meta.driver
    ? config.driver[action.meta.driver]
    : config.driver.default || config.driver;

const getLastActionKey = action =>
  action.type +
  (action.meta && action.meta.requestKey ? action.meta.requestKey : '');

// TODO: remove to more functional style, we need object maps and filters
const createSendRequestMiddleware = config => {
  // TODO: clean not pending promises sometimes
  const pendingRequests = {};

  return store => next => action => {
    if (action.type === ABORT_REQUESTS) {
      const clearAll = !action.requests;
      const keys = !clearAll && getKeys(action.requests);

      if (!action.requests) {
        Object.values(pendingRequests).forEach(requests =>
          requests.forEach(r => r.cancel()),
        );
      } else {
        Object.entries(pendingRequests)
          .filter(([k]) => keys.includes(k))
          .forEach(([, requests]) => requests.forEach(r => r.cancel()));
      }

      return next(action);
    }

    if (
      config.isRequestAction(action) &&
      (!action.meta || action.meta.runByWatcher !== false)
    ) {
      const driver = getDriver(config, action);
      const actionPayload = getActionPayload(action);
      const lastActionKey = getLastActionKey(action);
      const takeLatest =
        action.meta && action.meta.takeLatest !== undefined
          ? action.meta.takeLatest
          : typeof config.takeLatest === 'function'
          ? config.takeLatest(action)
          : config.takeLatest;

      if (takeLatest && pendingRequests[lastActionKey]) {
        pendingRequests[lastActionKey].forEach(r => r.cancel());
      }

      const isBatchedRequest = Array.isArray(actionPayload.request);
      const responsePromises = isBatchedRequest
        ? actionPayload.request.map(r => driver(r, action))
        : [driver(actionPayload.request, action)];

      if (responsePromises[0].cancel) {
        pendingRequests[lastActionKey] = responsePromises;
      }

      Promise.all(responsePromises)
        .then(response =>
          isBatchedRequest
            ? response.reduce(
                (prev, current) => {
                  prev.data.push(current.data);
                  return prev;
                },
                { data: [] },
              )
            : response[0],
        )
        .then(response => {
          if (
            action.meta &&
            !action.meta.cacheResponse &&
            !action.meta.ssrResponse &&<commit_msg>Handle cache and ssr cases in send requests middleware<commit_after>import {
  getActionPayload,
  createSuccessAction,
  createErrorAction,
  createAbortAction,
} from '../actions';
import { ABORT_REQUESTS } from '../constants';

const getRequestTypeString = requestType =>
  typeof requestType === 'function' ? requestType.toString() : requestType;

const getKeys = requests =>
  requests.map(v =>
    typeof v === 'object'
      ? getRequestTypeString(v.requestType) + v.requestKey
      : getRequestTypeString(v),
  );

const getDriver = (config, action) =>
  action.meta && action.meta.driver
    ? config.driver[action.meta.driver]
    : config.driver.default || config.driver;

const getLastActionKey = action =>
  action.type +
  (action.meta && action.meta.requestKey ? action.meta.requestKey : '');

// TODO: remove to more functional style, we need object maps and filters
const createSendRequestMiddleware = config => {
  // TODO: clean not pending promises sometimes
  const pendingRequests = {};

  return store => next => action => {
    if (action.type === ABORT_REQUESTS) {
      const clearAll = !action.requests;
      const keys = !clearAll && getKeys(action.requests);

      if (!action.requests) {
        Object.values(pendingRequests).forEach(requests =>
          requests.forEach(r => r.cancel()),
        );
      } else {
        Object.entries(pendingRequests)
          .filter(([k]) => keys.includes(k))
          .forEach(([, requests]) => requests.forEach(r => r.cancel()));
      }

      return next(action);
    }

    if (
      config.isRequestAction(action) &&
      (!action.meta || action.meta.runByWatcher !== false)
    ) {
      let responsePromises;
      const actionPayload = getActionPayload(action);
      const isBatchedRequest = Array.isArray(actionPayload.request);

      if (action.meta && action.meta.cacheResponse) {
        responsePromises = [Promise.resolve(action.meta.cacheResponse)];
      } else if (action.meta && action.meta.ssrResponse) {
        responsePromises = [Promise.resolve(action.meta.ssrResponse)];
      } else {
        const driver = getDriver(config, action);
        const lastActionKey = getLastActionKey(action);
        const takeLatest =
          action.meta && action.meta.takeLatest !== undefined
            ? action.meta.takeLatest
            : typeof config.takeLatest === 'function'
            ? config.takeLatest(action)
            : config.takeLatest;

        if (takeLatest && pendingRequests[lastActionKey]) {
          pendingRequests[lastActionKey].forEach(r => r.cancel());
        }

        responsePromises = isBatchedRequest
          ? actionPayload.request.map(r => driver(r, action))
          : [driver(actionPayload.request, action)];

        if (responsePromises[0].cancel) {
          pendingRequests[lastActionKey] = responsePromises;
        }
      }

      Promise.all(responsePromises)
        .then(response => {
          response =
            isBatchedRequest &&
            !action.meta.cacheResponse &&
            !action.meta.ssrResponse
              ? response.reduce(
                  (prev, current) => {
                    prev.data.push(current.data);
                    return prev;
                  },
                  { data: [] },
                )
              : response[0];

          if (
            action.meta &&
            !action.meta.cacheResponse &&
            !action.meta.ssrResponse &&
{'fraction_non_alphanumeric': 0.12457231726283048, 'fraction_numerical': 0.0006220839813374805, 'mean_word_length': 2.3883034773445733, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2564554', 'n_tokens_mistral': 1755, 'n_tokens_neox': 1737, 'n_words': 341}