{"version":3,"file":"parsingUtils.mjs","sources":["../../../src/querybuilder/parsingUtils.ts"],"sourcesContent":["// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/parsingUtils.ts\nimport { type SyntaxNode, type TreeCursor } from '@lezer/common';\nimport { AggregateExpr, FunctionCallBody } from '@prometheus-io/lezer-promql';\n\nimport { type QueryBuilderOperation, type QueryBuilderOperationParamValue } from './shared/types';\n\n// Although 0 isn't explicitly provided in the lezer-promql library as the error node ID, it does appear to be the ID of error nodes within lezer.\nexport const ErrorId = 0;\n\nexport function getLeftMostChild(cur: SyntaxNode): SyntaxNode {\n  return cur.firstChild ? getLeftMostChild(cur.firstChild) : cur;\n}\n\nexport function makeError(expr: string, node: SyntaxNode) {\n  return {\n    text: getString(expr, node),\n    // TODO: this are positions in the string with the replaced variables. Means it cannot be used to show exact\n    //  placement of the error for the user. We need some translation table to positions before the variable\n    //  replace.\n    from: node.from,\n    to: node.to,\n    parentType: node.parent?.name,\n  };\n}\n\n// Taken from template_srv, but copied so to not mess with the regex.index which is manipulated in the service\n/*\n * This regex matches 3 types of variable reference with an optional format specifier\n * \\$(\\w+)                          $var1\n * \\[\\[([\\s\\S]+?)(?::(\\w+))?\\]\\]    [[var2]] or [[var2:fmt2]]\n * \\${(\\w+)(?::(\\w+))?}             ${var3} or ${var3:fmt3}\n */\nconst variableRegex = /\\$(\\w+)|\\[\\[([\\s\\S]+?)(?::(\\w+))?\\]\\]|\\${(\\w+)(?:\\.([^:^\\}]+))?(?::([^\\}]+))?}/g;\n\n/**\n * As variables with $ are creating parsing errors, we first replace them with magic string that is\n * parsable and at the same time we can get the variable and its format back from it.\n */\nexport function replaceVariables(expr: string) {\n  const replacedVariables: Record<string, string> = {};\n  const replacedExpr = expr.replace(variableRegex, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {\n    const fmt = fmt2 || fmt3;\n    let variable = var1;\n    let varType = '0';\n\n    if (var2) {\n      variable = var2;\n      varType = '1';\n    }\n\n    if (var3) {\n      variable = var3;\n      varType = '2';\n    }\n\n    const replacement = `__V_${varType}__` + variable + '__V__' + (fmt ? '__F__' + fmt + '__F__' : '');\n    replacedVariables[replacement] = match;\n    return replacement;\n  });\n\n  return { replacedExpr, replacedVariables };\n}\n\nconst varTypeFunc = [\n  (v: string, f?: string) => `\\$${v}`,\n  (v: string, f?: string) => `[[${v}${f ? `:${f}` : ''}]]`,\n  (v: string, f?: string) => `\\$\\{${v}${f ? `:${f}` : ''}\\}`,\n];\n\n/**\n * Get back the text with variables in their original format.\n * @param expr\n */\nfunction returnVariables(expr: string) {\n  return expr.replace(/__V_(\\d)__(.+?)__V__(?:__F__(\\w+)__F__)?/g, (match, type, v, f) => {\n    return varTypeFunc[parseInt(type, 10)](v, f);\n  });\n}\n\n/**\n * Get the actual string of the expression. That is not stored in the tree so we have to get the indexes from the node\n * and then based on that get it from the expression.\n * @param expr\n * @param node\n */\nexport function getString(expr: string, node: SyntaxNode | TreeCursor | null | undefined) {\n  if (!node) {\n    return '';\n  }\n  return returnVariables(expr.substring(node.from, node.to));\n}\n\n/**\n * Create simple scalar binary op object.\n * @param opDef - definition of the op to be created\n * @param expr\n * @param numberNode - the node for the scalar\n * @param hasBool - whether operation has a bool modifier. Is used only for ops for which it makes sense.\n */\nexport function makeBinOp(\n  opDef: { id: string; comparison?: boolean },\n  expr: string,\n  numberNode: SyntaxNode,\n  hasBool: boolean\n): QueryBuilderOperation {\n  const params: QueryBuilderOperationParamValue[] = [parseFloat(getString(expr, numberNode))];\n  if (opDef.comparison) {\n    params.push(hasBool);\n  }\n  return {\n    id: opDef.id,\n    params,\n  };\n}\n\n/**\n * Get all nodes with type in the tree. This traverses the tree so it is safe only when you know there shouldn't be\n * too much nesting but you just want to skip some of the wrappers. For example getting function args this way would\n * not be safe is it would also find arguments of nested functions.\n * @param expr\n * @param cur\n * @param type\n */\nexport function getAllByType(expr: string, cur: SyntaxNode, type: number): string[] {\n  if (cur.type.id === type) {\n    return [getString(expr, cur)];\n  }\n  const values: string[] = [];\n  let pos = 0;\n  let child = cur.childAfter(pos);\n  while (child) {\n    values.push(...getAllByType(expr, child, type));\n    pos = child.to;\n    child = cur.childAfter(pos);\n  }\n  return values;\n}\n\n/**\n * There aren't any spaces in the metric names, so let's introduce a wildcard into the regex for each space to better facilitate a fuzzy search\n */\nexport const regexifyLabelValuesQueryString = (query: string) => {\n  const queryArray = query.split(' ');\n  return queryArray.map((query) => `${query}.*`).join('');\n};\n\n/**\n * Built-in Grafana variables used for time ranges and intervals in Prometheus queries\n * Each variable has a carefully crafted numeric replacement that:\n * 1. Has exactly the same string length as the original variable\n * 2. Is valid in Prometheus syntax to avoid parsing errors\n * 3. Preserves error position information for accurate error reporting\n * 4. Uses readable number formatting with digit grouping via underscores\n * https://prometheus.io/docs/prometheus/latest/querying/basics/#float-literals-and-time-durations\n */\nconst BUILT_IN_VARIABLES = [\n  { variable: '$__interval_ms', replacement: '79_999_999_999' },\n  { variable: '$__interval', replacement: '711_999_999' },\n  { variable: '$__rate_interval', replacement: '7999799979997999' },\n  { variable: '$__range_ms', replacement: '722_999_999' },\n  { variable: '$__range_s', replacement: '79_299_999' },\n  { variable: '$__range', replacement: '799_999' },\n];\n\n// Derived maps for efficient lookups\nconst variableToReplacement = BUILT_IN_VARIABLES.reduce<Record<string, string>>((map, { variable, replacement }) => {\n  map[variable] = replacement;\n  return map;\n}, {});\n\nconst replacementToVariable = BUILT_IN_VARIABLES.reduce<Record<string, string>>((map, { variable, replacement }) => {\n  map[replacement] = variable;\n  return map;\n}, {});\n\n// Pre-compiled regular expressions for efficient search/replace\nconst builtInVariablePattern = BUILT_IN_VARIABLES.map(({ variable }) => variable.replace(/\\$/g, '\\\\$')).join('|');\nconst builtInVariableRegex = new RegExp(builtInVariablePattern, 'g');\n\nconst builtInReplacementPattern = BUILT_IN_VARIABLES.map(({ replacement }) => replacement).join('|');\nconst builtInReplacementRegex = new RegExp(builtInReplacementPattern, 'g');\n\n/**\n * Replaces Grafana built-in variables with numeric replacements\n * This helps prevent these variables from causing parsing errors\n */\nexport function replaceBuiltInVariable(expr: string): string {\n  return expr.replace(builtInVariableRegex, (match) => variableToReplacement[match]);\n}\n\n/**\n * Restores the original built-in variables from their replacement format\n * Reverses the transformation done by replaceBuiltInVariable\n */\nexport function returnBuiltInVariable(expr: string): string {\n  return expr.replace(builtInReplacementRegex, (match) => replacementToVariable[match]);\n}\n\nexport function isFunctionOrAggregation(node: SyntaxNode): boolean {\n  return node.type.id === AggregateExpr || node.type.id === FunctionCallBody;\n}\n"],"names":["query"],"mappings":"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"}