All files collection-functions.ts

65.03% Statements 93/143
100% Branches 3/3
16.66% Functions 2/12
65.03% Lines 93/143

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 1441x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 45x 15x 15x 45x 45x 45x 1x 1x 1x 1x 1x         1x 1x 1x 1x 1x 1x 45x 45x 1x 1x 1x 1x 1x 1x     1x 1x 1x 1x 1x     1x 1x 1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x                       1x 1x 1x 1x 1x         1x 1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x 1x 1x               1x 1x 1x 1x 1x      
/**
 * Copyright (c) OpenLens Authors. All rights reserved.
 * Licensed under MIT License. See LICENSE in root directory for more information.
 */
 
import { runInAction } from "mobx";
import { inspect } from "util";
import { isDefined } from "./type-narrowing";
 
/**
 * Get the value behind `key`. If it was not present, first insert `value`
 * @param map The map to interact with
 * @param key The key to insert into the map with
 * @param value The value to optional add to the map
 * @returns The value in the map
 */
export function getOrInsert<K, V>(map: Map<K, V>, key: K, value: V): V {
  if (!map.has(key)) {
    map.set(key, value);
  }
 
  return map.get(key)!;
}
 
/**
 * Updates map and returns the value that was just inserted
 */
export function put<K, V>(map: Map<K, V>, key: K, value: V): V {
  map.set(key, value);

  return value;
}
 
/**
 * Like `getOrInsert` but specifically for when `V` is `Map<MK, MV>` so that
 * the typings are inferred correctly.
 */
export function getOrInsertMap<K, MK, MV>(map: Map<K, Map<MK, MV>>, key: K): Map<MK, MV> {
  return getOrInsert(map, key, new Map<MK, MV>());
}
 
/**
 * Like `getOrInsert` but specifically for when `V` is `Set<any>` so that
 * the typings are inferred.
 */
export function getOrInsertSet<K, SK>(map: Map<K, Set<SK>>, key: K): Set<SK> {
  return getOrInsert(map, key, new Set<SK>());
}
 
/**
 * A currying version of {@link getOrInsertSet}
 */
export function getOrInsertSetFor<K, SK>(map: Map<K, Set<SK>>): (key: K) => Set<SK> {
  return (key) => getOrInsertSet(map, key);
}
 
/**
 * Like `getOrInsert` but with delayed creation of the item. Which is useful
 * if it is very expensive to create the initial value.
 */
export function getOrInsertWith<K, V>(map: Map<K, V>, key: K, builder: () => V): V;
export function getOrInsertWith<K extends object, V>(map: Map<K, V> | WeakMap<K, V>, key: K, builder: () => V): V;
 
export function getOrInsertWith<K extends object, V>(map: Map<K, V> | WeakMap<K, V>, key: K, builder: () => V): V {
  if (!map.has(key)) {
    map.set(key, builder());
  }

  return map.get(key)!;
}
 
/**
 * Like {@link getOrInsertWith} but the builder is async and will be awaited before inserting into the map
 */
export async function getOrInsertWithAsync<K, V>(map: Map<K, V>, key: K, asyncBuilder: () => Promise<V>): Promise<V> {
  if (!map.has(key)) {
    const newValue = await asyncBuilder();

    runInAction(() => {
      map.set(key, newValue);
    });
  }

  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  return map.get(key)!;
}
 
/**
 * Insert `val` into `map` under `key` and then get the value back
 */
export function setAndGet<K, V>(map: Map<K, V>, key: K, val: V): V {
  map.set(key, val);

  return map.get(key)!;
}
 
/**
 * Set the value associated with `key` iff there was not a previous value
 * @param map The map to interact with
 * @throws if `key` already in map
 * @returns `this` so that `strictSet` can be chained
 */
export function strictSet<K, V>(map: Map<K, V>, key: K, val: V): typeof map {
  if (map.has(key)) {
    throw new TypeError(`Map already contains key: ${inspect(key)}`);
  }

  return map.set(key, val);
}
 
/**
 * Get the value associated with `key`
 * @param map The map to interact with
 * @throws if `key` did not a value associated with it
 */
export function strictGet<K, V>(map: Map<K, V>, key: K): V {
  if (!map.has(key)) {
    throw new TypeError(`Map does not contains key: ${inspect(key)}`);
  }

  return map.get(key)!;
}
 
/**
 * If `key` is in `set`, remove it otherwise add it.
 * @param set The set to manipulate
 * @param key The key to toggle the "is in"-ness of
 */
export function toggle<K>(set: Set<K>, key: K): void {
  runInAction(() => {
    // Returns true if value was already in Set; otherwise false.
    if (!set.delete(key)) {
      set.add(key);
    }
  });
}
 
/**
 * A helper function to also check for defined-ness
 */
export function includes<T>(src: T[], value: T | null | undefined): boolean {
  return isDefined(value) && src.includes(value);
}