export function transformKeyValue(key: string | string[], value: string | null, negative: boolean = false): string { if (Array.isArray(key)) { key = key.reduce((accumulator: string, element: string, index: number) => { if (index === 0) return `event->'${element}'` if (index === key.length - 1) return `${accumulator}->>'${element}'` return `${accumulator}->'${element}'` }, '') } else { key = `event->>'${key}'` } key = `COALESCE(lower(${key}), '')` if (!value) return `${key} IS ${negative ? 'NOT NULL' : 'NULL'}` value = value.replace(/\\(.)/g, '$1') // Unescape special characters if (!isNaN(Number(value))) { return `(${key})::int ${negative ? '!=' : '='} ${value}` } else if (value.match(/^'.*'$/)) { return `${key} ${negative ? '!=' : '='} lower(${value})` } else if (value.includes('*')) { return `${key} ${negative ? 'NOT ILIKE' : 'ILIKE'} lower('${value.replace(/\*/g, '%')}')` } else if (value.match(/[a-zA-Z]/)) { return `${key} ${negative ? 'NOT ILIKE' : 'ILIKE'} lower('%${value}%')` } else { return `${key} ${negative ? '!=' : '='} 'lower(${value})'` } } export function transformExclusion(key: string, value: string | null): string { return transformKeyValue(key, value, true) } export function transformOrGroup(key: string, value: string[]): string { return value.map((v) => transformKeyValue(key, v)).join(' OR ') } export function isNumeric(value: string): boolean { return !isNaN(parseFloat(value)) && isFinite(Number(value)) } export function transformKeyValueOrGroup(key: string, value: string): string { // Handle OR conditions if (value.includes(' OR ')) { return value .split(' OR ') .map((condition) => { return transformKeyValue(key, condition.replace(/^NOT /, ''), condition.startsWith('NOT ')) }) .join(' OR ') } // Handle single conditions (with or without NOT) return transformKeyValue(key, value.replace(/^NOT /, ''), value.startsWith('NOT ')) } // This function handles plain words or quoted phrases with no key, transforming them into fuzzy searches export function transformFuzzy(value: string): string { for (const quote of ["'", '"']) { if (value.startsWith(quote) && value.endsWith(quote)) { value = value.slice(1, -1) } } return `event::text ILIKE '%${value}%'` }