The raw search string from the search box.
The parsed query (always usable; never throws).
parseSearchQuery("acetone");
// { raw: "acetone", ast: { type: "term", value: "acetone", phrase: false }, isAdvanced: false }
parseSearchQuery("Carbonate AND (Sodium OR Potassium)");
// { isAdvanced: true, ast: { type: "and", left: {term Carbonate}, right: { type: "or", ... } } }
export function parseSearchQuery(input: string): ParsedSearchQuery {
const trimmed = input.trim();
if (trimmed === '') {
return { raw: input, ast: { type: 'term', value: '', phrase: false }, isAdvanced: false };
}
if (!hasAdvancedSyntax(trimmed)) {
return {
raw: input,
ast: { type: 'term', value: trimmed, phrase: trimmed.includes(' ') },
isAdvanced: false,
};
}
try {
const ast = normalizeLiqeNode(parseLiqe(quotePhrases(trimmed)));
return { raw: input, ast, isAdvanced: true };
} catch {
// Malformed advanced syntax — fall back to a plain search over the raw text.
return {
raw: input,
ast: { type: 'term', value: trimmed, phrase: trimmed.includes(' ') },
isAdvanced: false,
};
}
}
Parses a raw user search string into a ParsedSearchQuery.
A plain query (no operators/parens) returns a single-term AST with
isAdvanced: false, so every downstream consumer can preserve today's exact behavior. Any parse failure — unbalanced parentheses, a dangling operator, unsupported syntax — degrades gracefully to that same plain single-term form rather than throwing, so a malformed advanced query never breaks a search.