All files / modules/10-common/utils rsql.ts

94.44% Statements 34/36
86.67% Branches 13/15
86.67% Functions 13/15
94.12% Lines 32/34

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                        626x           21x       12x     9x   1x     11x     626x 5x     626x   626x       626x   626x 1x     626x   626x 1x     626x   626x 1x     626x   626x 1x     626x   626x 3x     626x       626x 7x 2x     626x 2x 1x    
/*
 * Copyright 2020 Harness Inc. All rights reserved.
 * Use of this source code is governed by the PolyForm Shield 1.0.0 license
 * that can be found in the licenses directory at the root of this repository, also available at
 * https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt.
 */
 
// This utility toolkip provides functions to generate RSQL strings
// RSQL grammar and semantics can be found here: https://github.com/jirutka/rsql-parser#grammar-and-semantic
// eg. usage: and(equals('name', 'john'), includes('age', [20, 30, 40]))) => equivalent to "name is john and age is in (20, 30, 40)"
// you can also use the shorthand notation like and(eq('name', 'john'), gt('year', 2020))
 
const reservedCharacters = /"|'|\(|\)|;|,|=|!|~|<|>/
 
type Value = string | number
type Operator = '==' | '!=' | '=lt=' | '=gt=' | '=le=' | '=ge=' | '=in=' | '=out='
 
function valid(val: string): boolean {
  return !reservedCharacters.test(val)
}
 
function getExpression(operator: Operator, field: string, value: Value | Value[]): string {
  if (
    !valid(field) || // test field
    (typeof value === 'string' && !valid(value)) || // test value if value is string
    (value instanceof Array && value.filter(val => typeof val === 'string' && !valid(val)).length > 0) // test all string values if value is an array
  ) {
    throw new Error('String contains reserved characters')
  }
 
  return `${field}${operator}${value instanceof Array ? `(${value.join(',')})` : value}`
}
 
export function equals(field: string, value: Value): string {
  return getExpression('==', field, value)
}
 
export const eq = equals
 
export function notEquals(field: string, value: Value): string {
  return getExpression('!=', field, value)
}
 
export const ne = notEquals
 
export function lessThan(field: string, value: Value): string {
  return getExpression('=lt=', field, value)
}
 
export const lt = lessThan
 
export function greaterThan(field: string, value: Value): string {
  return getExpression('=gt=', field, value)
}
 
export const gt = greaterThan
 
export function lessThanOrEquals(field: string, value: Value): string {
  return getExpression('=le=', field, value)
}
 
export const le = lessThanOrEquals
 
export function greaterThanOrEquals(field: string, value: Value): string {
  return getExpression('=ge=', field, value)
}
 
export const ge = greaterThanOrEquals
 
export function includes(field: string, value: Array<Value>): string {
  return getExpression('=in=', field, value)
}
 
export function excludes(field: string, value: Array<Value>): string {
  return getExpression('=out=', field, value)
}
 
export function and(...args: Array<string | undefined>): string {
  args = args.filter(arg => arg !== undefined)
  return args.length ? `(${args.join(';')})` : ''
}
 
export function or(...args: Array<string | undefined>): string {
  args = args.filter(arg => arg !== undefined)
  return args.length ? `(${args.join(',')})` : ''
}