/ node_modules / @jet / environment / json / reader / key-path.js
key-path.js
  1  "use strict";
  2  Object.defineProperty(exports, "__esModule", { value: true });
  3  exports.keyPathContains = exports.keyPathEndsWith = exports.keyPathStartsWith = exports.keyPathsEqual = exports.isKeyPathThis = exports.thisKeyPath = exports.keysOf = void 0;
  4  const optional_1 = require("../../types/optional");
  5  /**
  6   * A global cache containing parsed string key paths
  7   * with components separated by a dot.
  8   */
  9  const parsedKeyPaths = {};
 10  /**
 11   * Extract the individual keys from a key path in order
 12   * to traverse into an object to access a specific value.
 13   *
 14   * @param keyPath - A key path to extract the keys from.
 15   * @returns An array containing the keys making up `keyPath`.
 16   */
 17  function keysOf(keyPath) {
 18      // TODO: Normalizing into an array is potentially a bottleneck.
 19      //       Do we want to do this differently for slower environments?
 20      if (Array.isArray(keyPath)) {
 21          return keyPath;
 22      }
 23      else {
 24          switch (typeof keyPath) {
 25              case "string": {
 26                  const existingKeyPath = parsedKeyPaths[keyPath];
 27                  if ((0, optional_1.isSome)(existingKeyPath)) {
 28                      return existingKeyPath;
 29                  }
 30                  else {
 31                      const newKeyPath = Object.freeze(keyPath.split("."));
 32                      parsedKeyPaths[keyPath] = newKeyPath;
 33                      return newKeyPath;
 34                  }
 35              }
 36              case "number": {
 37                  return [keyPath];
 38              }
 39              case "symbol": {
 40                  return [keyPath];
 41              }
 42              default: {
 43                  throw new TypeError(`${keyPath.toString()} is not a KeyPath`);
 44              }
 45          }
 46      }
 47  }
 48  exports.keysOf = keysOf;
 49  /**
 50   * A key path representing an object itself.
 51   */
 52  exports.thisKeyPath = Object.freeze([]);
 53  /**
 54   * Determine whether a given key path is the `this` (identity) key path.
 55   * @param keyPath - A key path to test.
 56   */
 57  function isKeyPathThis(keyPath) {
 58      return Array.isArray(keyPath) && keyPath.length === 0;
 59  }
 60  exports.isKeyPathThis = isKeyPathThis;
 61  /**
 62   * Determines whether two key paths are equivalent taking into account
 63   * that the key paths may have different representations.
 64   *
 65   * @param lhs - A key path to compare.
 66   * @param rhs - Another key path to compare.
 67   */
 68  function keyPathsEqual(lhs, rhs) {
 69      // 1. Are the key paths equal through value semantics?
 70      if (lhs === rhs) {
 71          return true;
 72      }
 73      const lhsKeys = keysOf(lhs);
 74      const rhsKeys = keysOf(rhs);
 75      // 2. Do we have the same number of keys in each path?
 76      if (lhsKeys.length !== rhsKeys.length) {
 77          return false;
 78      }
 79      // 3. Do any of the keys in our paths differ?
 80      for (let index = 0, length = lhsKeys.length; index < length; index += 1) {
 81          if (lhsKeys[index] !== rhsKeys[index]) {
 82              return false;
 83          }
 84      }
 85      // 4. We have passed all checks and are considered equal.
 86      return true;
 87  }
 88  exports.keyPathsEqual = keyPathsEqual;
 89  /**
 90   * Determine whether a given key path starts with a specified key.
 91   *
 92   * @param haystack - A key path to perform a prefix check on.
 93   * @param needle - The key to check for.
 94   */
 95  function keyPathStartsWith(haystack, needle) {
 96      if (haystack === needle) {
 97          return true;
 98      }
 99      else {
100          const keys = keysOf(haystack);
101          if (keys.length === 0) {
102              return false;
103          }
104          return keys[0] === needle;
105      }
106  }
107  exports.keyPathStartsWith = keyPathStartsWith;
108  /**
109   * Determine whether a given key path ends with a specified key.
110   *
111   * @param haystack - A key path to perform a suffix check on.
112   * @param needle - The key to check for.
113   */
114  function keyPathEndsWith(haystack, needle) {
115      if (haystack === needle) {
116          return true;
117      }
118      else {
119          const keys = keysOf(haystack);
120          if (keys.length === 0) {
121              return false;
122          }
123          return keys[keys.length - 1] === needle;
124      }
125  }
126  exports.keyPathEndsWith = keyPathEndsWith;
127  /**
128   * Determine whether a given key path contains a specified key.
129   *
130   * @param haystack - A key path to search.
131   * @param needle - The key to search for.
132   */
133  function keyPathContains(haystack, needle) {
134      if (haystack === needle) {
135          return true;
136      }
137      else {
138          const keys = keysOf(haystack);
139          return keys.includes(needle);
140      }
141  }
142  exports.keyPathContains = keyPathContains;
143  //# sourceMappingURL=key-path.js.map