Vulcan often use utils from 'utils/selectors'
eg:
from import { selectBulkFactory } from 'utils/selectors';

That's the available utils:

import { isObject } from 'lodash-es';
import { createSelector, createSelectorCreator, lruMemoize, weakMapMemoize } from 'reselect';
import type { RootState } from 'store/types';

export interface Entity {
  id: number | string;
  [key: string]: any;
}

// memoization is not needed here
export const selectOneFactory =
  <E extends Entity>(sliceName: string) =>
  (state: any, id: E['id']) =>
    state[sliceName][id] as E | undefined;

// memoize only the last result
export const selectAllFactory = <E extends Entity>(sliceName: string) =>
  createSelector(
    (state: any) => state[sliceName],
    state => Object.values(state) as E[],
    {
      memoize: lruMemoize,
      argsMemoize: lruMemoize,
    }
  );

// WeakMap based cache with infinite cache size. Cache results will be kept in memory as long as references
// to the arguments still exist, and then cleared out as the arguments are garbage-collected.
// we use custom resultEqualityCheck to sahllow compare the array of entities
export const selectBulkFactory = <E extends Entity>(sliceName: string) =>
  createSelector(
    [(state: any) => state[sliceName], (state: any, ids: E['id'][]) => ids],
    (state, ids) => (ids || []).map(id => state[id]) as E[],
    {
      memoize: weakMapMemoize,
      memoizeOptions: {
        resultEqualityCheck: arrayShallowEqual,
      },
      argsMemoize: weakMapMemoize,
    }
  );

function arrayShallowEqual(a: Entity[], b: Entity[]) {
  if (!Array.isArray(a) || !Array.isArray(b)) {
    return a === b;
  }
  if (a.length !== b.length) {
    return false;
  }
  for (let i = 0; i < a.length; i++) {
    if (a[i] !== b[i]) {
      return false;
    }
  }
  return true;
}

export function asSelector<Args extends unknown[], Selected>(
  fn: (state: RootState, ...args: Args) => Selected,
  ...args: Args
) {
  return (state: RootState) => fn(state, ...args);
}

// this aims to provide the behavior of createCachedMapSelector in the monolith
export const createResultCompareSelector = createSelectorCreator({
  memoize: weakMapMemoize,
  memoizeOptions: { resultEqualityCheck: shallowEqual },
});

export function shallowEqual(values: unknown, newValues: unknown): boolean {
  if (values === newValues) {
    return true;
  }

  const valuesEmpty = !values;
  const newValuesEmpty = !newValues;
  if (valuesEmpty && newValuesEmpty) {
    return true;
  }
  if (newValuesEmpty !== valuesEmpty) {
    return false;
  }

  if (!isObject(values) || !isObject(newValues)) {
    return values === newValues;
  }

  const valueKeys = Object.keys(values) as (keyof typeof values)[];
  const valuesSize = valueKeys.length;
  const newValuesSize = Object.keys(newValues).length;

  if (valuesSize !== newValuesSize) {
    return false;
  }

  for (const key of valueKeys) {
    if (values[key] !== newValues[key]) {
      return false;
    }
  }

  return true;
}
