Source: resolver/utils.js

import { fmtIter } from '../utils/generic';

/**
 * Before resolving an entity, ensures that `DockAPI` is initialized, throws an error otherwise.
 * @template T
 * @param {T} resolverClass
 * @param {function(T): DockAPI} pickDockAPI
 * @returns {T}
 */
export const withInitializedDockAPI = (
  resolverClass,
  pickDockAPI = ({ dock }) => dock,
) => class extends resolverClass {
  async resolve(url) {
    if (pickDockAPI(this).isInitialized()) {
      return super.resolve(url);
    } else {
      throw new Error('DockAPI is not connected');
    }
  }
};

/**
 * Caches last function result and returns it if function called with the same args again.
 * @param {Function}
 * @returns {Function}
 */
export const cacheLast = (fn) => {
  let lastArgs;
  let lastValue;

  return function cached(...args) {
    if (lastArgs !== void 0) {
      let same = true;
      const length = Math.max(lastArgs.length, args.length);
      for (let i = 0; i < length && same; ++i) {
        same &&= lastArgs[i] === args[i];
      }

      if (same) {
        return lastValue;
      }
    }
    lastValue = fn.apply(this, args);
    lastArgs = args;

    return lastValue;
  };
};

/**
 * Ensures that each item is present in the allowed set and that both sets are valid.
 *
 * @template T
 * @param {Iterable<T>} items
 * @param {Iterable<T>} allowed
 * @param {T} wildcard
 */
export const ensureItemsAllowed = (items, allowed, wildcard) => {
  const itemsSet = new Set(items);
  const allowedSet = new Set(allowed);
  if (items.size === 0) {
    throw new Error('Empty item set provided');
  }
  if (allowed.size === 0) {
    throw new Error('Empty allowed set provided');
  }

  for (const toCheck of [itemsSet, allowedSet]) {
    if (toCheck.has(wildcard) && toCheck.size > 1) {
      throw new Error(
        `Can't have wildcard mixed with other patterns for ${fmtIter(toCheck)}`,
      );
    }
  }

  if (allowedSet.has(wildcard)) return;

  for (const item of itemsSet) {
    if (!allowedSet.has(item)) {
      throw new Error(
        `Item not found in ${fmtIter(allowedSet)}: \`${item.toString()}\``,
      );
    }
  }
};