jmeas/redux-resource

View on GitHub
packages/redux-resource/src/utils/get-resources.js

Summary

Maintainability
B
5 hrs
Test Coverage
import warning from './warning';

function resourceArrayToObject(arr) {
  return arr.reduce((memo, r) => {
    memo[r.id] = r;
    return memo;
  }, {});
}

// Returns a list of resources by IDs or list name
export default function(resourceSlice, filter, options) {
  if (process.env.NODE_ENV !== 'production') {
    // We use duck typing to try and differentiate between a user passing the entire state tree
    // in as `resourceSlice` (which was the original getResources API).
    // eslint-disable-next-line no-inner-declarations
    function validateSlice(slice = {}) {
      return (
        // eslint-disable-next-line no-prototype-builtins
        slice.hasOwnProperty('resources') &&
        // eslint-disable-next-line no-prototype-builtins
        slice.hasOwnProperty('meta') &&
        // eslint-disable-next-line no-prototype-builtins
        slice.hasOwnProperty('requests') &&
        // eslint-disable-next-line no-prototype-builtins
        slice.hasOwnProperty('lists')
      );
    }

    if (
      arguments.length === 3 &&
      !validateSlice(resourceSlice) &&
      // We assume that undefined means that a slice is undefined, rather than the entire state tree being undefined.
      typeof resourceSlice !== 'undefined'
    ) {
      warning(
        `You called getResources with an argument signature that was removed in ` +
          `v3.0.0 of Redux Resource. The old signature accepted three arguments, with the first being the all of the store's ` +
          `state. The new signature of this function requires passing a resource slice as the first argument. Please ` +
          `update your code to use the new signature. For more information, reference the documentation at ` +
          `https://redux-resource.js.org/docs/api-reference/get-resources.html\n\n` +
          `Also, the migration guide to Redux Resource v3 can be found at: ` +
          `https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource/docs/migration-guides/2-to-3.md`,
        'DEPRECATED_GET_RESOURCES_SIGNATURE'
      );
    }
  }

  let byId;
  if (options && options.byId) {
    byId = options.byId;
  }

  const noResultsReturn = byId ? {} : [];

  if (!resourceSlice) {
    return noResultsReturn;
  }

  const resources = resourceSlice.resources;
  let idsList;

  if (typeof filter === 'function' || !filter) {
    const appliedFilter = filter ? filter : () => true;
    const resourcesList = Object.values(resources).filter(resource =>
      appliedFilter(resource, resourceSlice.meta[resource.id], resourceSlice)
    );

    return byId ? resourceArrayToObject(resourcesList) : resourcesList;
  } else if (typeof filter === 'string') {
    // This conditional handles the situation where `filter` is an list name
    const list = resourceSlice.lists[filter];
    if (!list) {
      return noResultsReturn;
    }

    idsList = list;
  } else {
    idsList = filter;
  }

  if (!(idsList && idsList.length)) {
    return noResultsReturn;
  }

  const resourcesList = idsList.map(id => resources[id]).filter(Boolean);

  return byId ? resourceArrayToObject(resourcesList) : resourcesList;
}