export function parseQuery()

in src/components/LogViewer/QueryBar.tsx [90:190]


export function parseQuery(query: string): ParsedQuery {
  let escapedQuery = '';
  let isEscaped = false;

  for (const char of query) {
    if (isEscaped) {
      escapedQuery += 'ˍ';
      isEscaped = false;
    } else {
      escapedQuery += char;

      if (char === '\\') {
        isEscaped = true;
      }
    }
  }

  const quoted_query = escapedQuery
    .split('"')
    .map((t, i) => (i % 2 ? t.replace(/ /g, 'ˍ') : t))
    .join('"');

  const sections: string[] = quoted_query
    .split('\n')
    .reduce((sections, line) => {
      return [
        ...sections,
        ...line.split(/((?:[^\s]+)\s?=\s?(?:[^\s]+))/),
        '\n',
      ];
    }, [] as string[]);

  const filters: { [key: string]: string } = {};
  const queryChunks: string[] = [];

  let position = 0;
  const elements = sections.map((quoted_section, index) => {
    const section = query.slice(position, position + quoted_section.length);
    position += quoted_section.length;

    const equalPosition = section.indexOf('=');
    const isKeyPair =
      equalPosition > -1 && section[0] !== '=' && section.slice(-1)[0] !== '=';
    const isNewline = section === '\n';

    if (isNewline) {
      return <br key={index} />;
    }
    if (!isKeyPair) {
      queryChunks.push(section);
      return (
        <span key={index} className="text">
          {section}
        </span>
      );
    }

    const pairKey = section.split('=')[0].trim();
    if (
      isKeyPair &&
      queryFields.indexOf(pairKey) === -1 &&
      !(pairKey.startsWith('user.') || pairKey.startsWith('user['))
    ) {
      return (
        <span key={index}>
          <span className="invalid_pair">{section}</span>
        </span>
      );
    }

    const [key, value] = section.split('=');
    try {
      filters[key.trim()] = JSON.parse(value);
    } catch (err) {
      filters[key.trim()] = value;
    }
    return (
      <span key={index}>
        <span className="key">{key}=</span>
        <span className="value">{value}</span>
      </span>
    );
  });

  const search = [
    filters.search,
    queryChunks
      .filter((v) => v)
      .join(' ')
      .trim(),
  ]
    .filter((v) => v)
    .join(' ');

  if (search.length) filters.search = search;

  return {
    elements,
    filters,
  };
}