react query builder basic filters + must_not/should change + groupKey + exists Clause

by alfredopacino

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
  text-align: center;
}

TypeScript

/**
 * OpenSearch QueryBuilder for basic filters.
 *
 * It supports the following cases:
 *
 * 1. **Top-level fields**
 *    Generates either a `term`, `terms` (for arrays), or a `range` query.
 *    Examples:
 *      { field: "variantCategory", value: "small" }
 *      { field: "variantCategory", value: ["cnv", "structural"] }
 *      { field: "start", value: { lte: 1 } }
 *
 * 2. **Indexed nested fields**
 *    Fields indexed as nested objects in OpenSearch.
 *    Example: { field: "genes.genePanels.source", value: ["NGTD", "AWSD"] }
 *
 * 3. **Nested fields that are not entirely indexed as nested**
 *    Allows overriding the nesting level through `nestedPath` in `queryConfig`. In case nestedPath is null, the field is treated as top-level.
 *    Example: { field: "reportEvents.vendorSpecificScores.rank", value: { lte: 1 }, queryConfig: { nestedPath: "reportEvents" } }
 *
 * 4. **Fields that imply additional underlying query terms**
 *    Uses `requiredTerm` in `queryConfig` to inject another QueryTerm.
 *    Example: { field: "reportEvents.vendorSpecificScores.rank", value: { lte: 1 }, queryConfig: { nestedPath: "reportEvents", requiredTerm: { field: "reportEvents.interpretationService", value: "Exomiser" } } }
 *
 * 5. **Special-case fields with ad-hoc render (exceptionTerms())**
 *    Example: { field: "size", value: { lte: 1 } }
 *
 * 6. **Boolean operator per term**
 *    Use `queryConfig.bool` to choose 'must' | 'must_not' | 'should'. Defaults to 'must'.
 *
 * 7. **Minimum Should Match**
 *    Optionally provide `minimum_should_match` at the root via `opts.root.minimum_should_match`,
 *    and/or per nested path via `opts.nested["path.to.nested"] = number | string`.
 *
 * 8. **Nested merging/splitting**
 *    Nested filters with incompatible queryConfig.requiredTerm are split into separate nested clauses.
 *
 * 9. **Exists checks**
 *    Use { exists: true } or { exists: false } as value to generate exists or must_not...