All files / builder buildScopedSegments.ts

100% Statements 64/64
100% Branches 21/21
100% Functions 15/15
100% Lines 59/59

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 144 145 146 147 148 149 150 151 152 153 154                  2x           112x 112x   112x     2x     376x 209x     167x   39x     39x     18x 9x     9x     149x 80x 39x 99x   99x     39x 21x     18x         41x 28x 69x   69x     28x 6x     22x         13x 13x 30x   30x     13x 7x     6x           69x     2x           354x 22x     332x 23x 45x       309x 228x 85x     143x   143x 67x       157x   81x 37x   75x         44x 31x   61x         13x 13x   18x           76x    
import type {
  GroupSegment,
  AndGroupSegment,
  OrGroupSegment,
  NotGroupSegment,
  Context,
} from "@featurevisor/types";
import type { DatafileReader } from "@featurevisor/sdk";
 
export function buildScopedSegments(
  datafileReader: DatafileReader,
  segments: GroupSegment | GroupSegment[],
  context: Context,
  removeSegments: string[] = [],
): GroupSegment | GroupSegment[] {
  const scoped = buildScopedGroupSegments(datafileReader, segments, context, removeSegments);
  const removed = removeRedundantGroupSegments(scoped);
 
  return removed;
}
 
export function removeRedundantGroupSegments(
  groupSegments: GroupSegment | GroupSegment[],
): GroupSegment | GroupSegment[] {
  if (groupSegments === "*") {
    return groupSegments;
  }
 
  if (Array.isArray(groupSegments)) {
    // Recursively process each group segment
    const processed = groupSegments.map((gs) => removeRedundantGroupSegments(gs)) as GroupSegment[];
 
    // Filter out "*" values
    const filtered = processed.filter((gs) => gs !== "*");
 
    // If all were "*", return "*"
    if (filtered.length === 0) {
      return "*";
    }
 
    return filtered;
  }
 
  if (typeof groupSegments === "object") {
    if ("and" in groupSegments) {
      const processed = groupSegments.and.map((gs) =>
        removeRedundantGroupSegments(gs),
      ) as GroupSegment[];
      const filtered = processed.filter((gs) => gs !== "*");
 
      // If all were "*", return "*"
      if (filtered.length === 0) {
        return "*";
      }
 
      return {
        and: filtered,
      } as AndGroupSegment;
    }
 
    if ("or" in groupSegments) {
      const processed = groupSegments.or.map((gs) =>
        removeRedundantGroupSegments(gs),
      ) as GroupSegment[];
      const filtered = processed.filter((gs) => gs !== "*");
 
      // If all were "*", return "*"
      if (filtered.length === 0) {
        return "*";
      }
 
      return {
        or: filtered,
      } as OrGroupSegment;
    }
 
    if ("not" in groupSegments) {
      const processed = groupSegments.not.map((gs) =>
        removeRedundantGroupSegments(gs),
      ) as GroupSegment[];
      const filtered = processed.filter((gs) => gs !== "*");
 
      // If all were "*", return "*"
      if (filtered.length === 0) {
        return "*";
      }
 
      return {
        not: filtered,
      } as NotGroupSegment;
    }
  }
 
  return groupSegments;
}
 
export function buildScopedGroupSegments(
  datafileReader: DatafileReader,
  groupSegments: GroupSegment | GroupSegment[],
  context: Context,
  removeSegments: string[] = [],
): GroupSegment | GroupSegment[] {
  if (groupSegments === "*") {
    return groupSegments;
  }
 
  if (Array.isArray(groupSegments)) {
    return groupSegments.map((gs) =>
      buildScopedGroupSegments(datafileReader, gs, context, removeSegments),
    ) as GroupSegment[];
  }
 
  if (typeof groupSegments === "string") {
    if (removeSegments.includes(groupSegments)) {
      return "*";
    }
 
    const matched = datafileReader.allSegmentsAreMatched(groupSegments, context);
 
    if (matched) {
      return "*";
    }
  }
 
  if (typeof groupSegments === "object") {
    // AND, OR, NOT group segments
    if ("and" in groupSegments) {
      return {
        and: groupSegments.and.map((gs) =>
          buildScopedGroupSegments(datafileReader, gs, context, removeSegments),
        ) as GroupSegment[],
      } as AndGroupSegment;
    }
 
    if ("or" in groupSegments) {
      return {
        or: groupSegments.or.map((gs) =>
          buildScopedGroupSegments(datafileReader, gs, context, removeSegments),
        ) as GroupSegment[],
      } as OrGroupSegment;
    }
 
    if ("not" in groupSegments) {
      return {
        not: groupSegments.not.map((gs) =>
          buildScopedGroupSegments(datafileReader, gs, context, removeSegments),
        ) as GroupSegment[],
      } as NotGroupSegment;
    }
  }
 
  return groupSegments;
}