{"version":3,"file":"parseSpEL.mjs","names":[],"sources":["../src/utils/parseSpEL/utils.ts","../src/utils/parseSpEL/parseSpEL.ts"],"sourcesContent":["import type { DefaultCombinatorName, DefaultOperatorName } from '../../types';\nimport type {\n  SpELBaseNode,\n  SpELBetweenFields,\n  SpELBetweenValues,\n  SpELBooleanLiteral,\n  SpELCompoundNode,\n  SpELExpressionNode,\n  SpELIdentifier,\n  SpELListNode,\n  SpELMethodCall,\n  SpELMethodNode,\n  SpELNodeType,\n  SpELNullLiteral,\n  SpELNumericLiteral,\n  SpELOpAnd,\n  SpELOpMatches,\n  SpELOpOr,\n  SpELPrimitive,\n  SpELProcessedExpression,\n  SpELPropertyNode,\n  SpELQualifiedIdentifierNode,\n  SpELRelOpType,\n  SpELRelation as SpELRelationOp,\n  SpELStringLiteral,\n} from './types';\n\nexport const isSpELPropertyNode = (expr: SpELBaseNode<SpELNodeType>): expr is SpELPropertyNode => {\n  return expr.getType() === 'property' || expr.getType() === 'variable';\n};\nexport const isSpELCompoundNode = (expr: SpELBaseNode<SpELNodeType>): expr is SpELCompoundNode => {\n  return expr.getType() === 'compound' && expr.getChildren().every(c => isSpELPropertyNode(c));\n};\nexport const isSpELListNode = (expr: SpELBaseNode<SpELNodeType>): expr is SpELListNode => {\n  return expr.getType() === 'list';\n};\n\nexport const isSpELOpAnd = (expr: SpELProcessedExpression): expr is SpELOpAnd =>\n  expr.type === 'op-and';\nexport const isSpELOpOr = (expr: SpELProcessedExpression): expr is SpELOpOr =>\n  expr.type === 'op-or';\nexport const isSpELOpMatches = (expr: SpELProcessedExpression): expr is SpELOpMatches =>\n  expr.type === 'matches' &&\n  ((isSpELIdentifier(expr.children[0]) && isSpELStringLiteral(expr.children[1])) ||\n    (isSpELIdentifier(expr.children[1]) && isSpELStringLiteral(expr.children[0])) ||\n    (isSpELIdentifier(expr.children[0]) && isSpELIdentifier(expr.children[1])));\nexport const isSpELIdentifier = (expr: SpELProcessedExpression): expr is SpELIdentifier =>\n  (expr.type === 'property' || expr.type === 'variable' || expr.type === 'compound') &&\n  expr.identifier !== null;\nexport const isSpELStringLiteral = (expr: SpELProcessedExpression): expr is SpELStringLiteral =>\n  expr.type === 'string';\nexport const isSpELNumericLiteral = (expr: SpELProcessedExpression): expr is SpELNumericLiteral =>\n  expr.type === 'number';\nexport const isSpELBooleanLiteral = (expr: SpELProcessedExpression): expr is SpELBooleanLiteral =>\n  expr.type === 'boolean';\nexport const isSpELNullLiteral = (expr: SpELProcessedExpression): expr is SpELNullLiteral =>\n  expr.type === 'null';\nexport const isSpELRelationOp = (expr: SpELProcessedExpression): expr is SpELRelationOp =>\n  expr.type === 'op-eq' ||\n  expr.type === 'op-ne' ||\n  expr.type === 'op-gt' ||\n  expr.type === 'op-ge' ||\n  expr.type === 'op-lt' ||\n  expr.type === 'op-le';\nexport const isSpELPrimitive = (expr: SpELProcessedExpression): expr is SpELPrimitive =>\n  isSpELNumericLiteral(expr) ||\n  isSpELStringLiteral(expr) ||\n  isSpELBooleanLiteral(expr) ||\n  isSpELNullLiteral(expr);\nexport const isSpELBetweenValues = (expr: SpELProcessedExpression): expr is SpELBetweenValues =>\n  expr.type === 'between' &&\n  isSpELIdentifier(expr.children[0]) &&\n  expr.children[1].type === 'list' &&\n  expr.children[1].children.length >= 2 &&\n  expr.children[1].children.every(c => isSpELPrimitive(c));\nexport const isSpELBetweenFields = (expr: SpELProcessedExpression): expr is SpELBetweenFields =>\n  expr.type === 'between' &&\n  isSpELIdentifier(expr.children[0]) &&\n  expr.children[1].type === 'list' &&\n  expr.children[1].children.length >= 2 &&\n  expr.children[1].children.every(c => isSpELIdentifier(c));\n\n/** A SpEL arithmetic infix node (`op-plus`/`op-minus`/`op-multiply`/`op-divide`/`op-modulus`). */\nexport const isSpELMathOperation = (expr: SpELProcessedExpression): boolean =>\n  expr.type === 'op-plus' ||\n  expr.type === 'op-minus' ||\n  expr.type === 'op-multiply' ||\n  expr.type === 'op-divide' ||\n  expr.type === 'op-modulus';\n\n/** A method/function invocation node (`.toUpperCase()`, `T(java.lang.Math).abs(x)`, `myFunc(a)`). */\nexport const isSpELMethodCall = (expr: SpELProcessedExpression): expr is SpELMethodCall =>\n  expr.type === 'method' && typeof expr.methodName === 'string';\n\n/**\n * Whether a relation operand should be routed to `getExpression`: an arithmetic infix node or a\n * method/function invocation. Bare identifiers, chains, and literals are not expression operands\n * (they retain their normal handling).\n */\nexport const isSpELExpressionOperand = (expr: SpELProcessedExpression): boolean =>\n  isSpELMathOperation(expr) || isSpELMethodCall(expr);\n\nexport const isSpELMethodNode = (expr: SpELBaseNode<SpELNodeType>): expr is SpELMethodNode =>\n  expr.getType() === 'method';\n\n/**\n * Builds a {@link SpELMethodCall} from a SpEL `method` node. Arguments are stored on the\n * compiled node's `getRaw()` payload (not as children), so they are processed from there.\n */\nconst processMethodNode = (\n  mn: SpELMethodNode,\n  target: SpELProcessedExpression | null,\n  typeRef: string | null\n): SpELMethodCall => {\n  const { methodName, args } = mn.getRaw();\n  return {\n    type: 'method',\n    children: args.map(a => processCompiledExpression(a)),\n    startPosition: mn.getStartPosition(),\n    endPosition: mn.getEndPosition(),\n    value: 'N/A',\n    identifier: null,\n    methodName,\n    target,\n    typeRef,\n  };\n};\n\n/**\n * Processes a SpEL `compound` node that invokes one or more methods, e.g. `name.toUpperCase()`,\n * `a.b.toLowerCase()`, `(a + b).toUpperCase()`, or `T(java.lang.Math).abs(cost)`. Leading\n * property/variable children are collapsed into a dotted receiver identifier, a leading `typeref`\n * becomes the `typeRef` of the first call, and each subsequent `method` child wraps the previous\n * result as its `target`. Returns `null` for chain shapes that can't be represented.\n */\nconst processMethodChain = (ce: SpELExpressionNode): SpELMethodCall | null => {\n  const children = ce.getChildren();\n  if (!children.some(c => isSpELMethodNode(c))) {\n    return null;\n  }\n\n  let index = 0;\n  let target: SpELProcessedExpression | null = null;\n  let typeRef: string | null = null;\n  const first = children[0];\n\n  if (first.getType() === 'typeref') {\n    const qualifiedIdentifier = first.getChildren()[0] as unknown as SpELQualifiedIdentifierNode;\n    typeRef = qualifiedIdentifier.getRaw().join('.');\n    index = 1;\n  } else if (isSpELPropertyNode(first)) {\n    const parts: string[] = [];\n    while (index < children.length && isSpELPropertyNode(children[index])) {\n      parts.push((children[index] as unknown as SpELPropertyNode).getRaw());\n      ++index;\n    }\n    target = {\n      type: parts.length > 1 ? 'compound' : first.getType(),\n      children: [],\n      startPosition: first.getStartPosition(),\n      endPosition: children[index - 1].getEndPosition(),\n      value: 'N/A',\n      identifier: parts.join('.'),\n    };\n  } else {\n    // Arbitrary receiver subtree, e.g. `(a + b).toUpperCase()`\n    target = processCompiledExpression(first);\n    index = 1;\n  }\n\n  let result: SpELMethodCall | null = null;\n  for (; index < children.length; ++index) {\n    const child = children[index];\n    if (!isSpELMethodNode(child)) {\n      return null;\n    }\n    result = processMethodNode(child, result ?? target, result ? null : typeRef);\n  }\n  return result;\n};\n\nexport const processCompiledExpression = (\n  ce: SpELPropertyNode | SpELExpressionNode\n): SpELProcessedExpression => {\n  const type = ce.getType();\n\n  // Bare function calls, e.g. `myFunc(a, b)`\n  if (isSpELMethodNode(ce)) {\n    return processMethodNode(ce, null, null);\n  }\n\n  // Method chains, e.g. `name.toUpperCase()` or `T(java.lang.Math).abs(cost)`\n  if (type === 'compound' && !isSpELCompoundNode(ce)) {\n    const methodChain = processMethodChain(ce);\n    if (methodChain) {\n      return methodChain;\n    }\n  }\n\n  const identifier = isSpELCompoundNode(ce)\n    ? ce\n        .getChildren()\n        .map(p => (isSpELPropertyNode(p) ? p.getRaw() : /* v8 ignore next -- @preserve */ ''))\n        .join('.')\n    : isSpELPropertyNode(ce)\n      ? ce.getRaw()\n      : null;\n  const children =\n    type === 'compound'\n      ? []\n      : (isSpELListNode(ce) ? ce.getRaw : ce.getChildren)().map(c => processCompiledExpression(c));\n  const startPosition = ce.getStartPosition();\n  const endPosition = ce.getEndPosition();\n  const value = ce.getValue.length === 0 ? ce.getValue() : 'N/A';\n\n  return {\n    type: type === 'compound' && !identifier ? 'invalid' : type,\n    children,\n    startPosition,\n    endPosition,\n    value,\n    identifier,\n  };\n};\n\nexport const normalizeOperator = (opType: SpELRelOpType, flip?: boolean): DefaultOperatorName => {\n  if (flip) {\n    if (opType === 'op-lt') return '>';\n    if (opType === 'op-le') return '>=';\n    if (opType === 'op-gt') return '<';\n    if (opType === 'op-ge') return '<=';\n  }\n  return (\n    {\n      'op-eq': '=',\n      'op-ge': '>=',\n      'op-gt': '>',\n      'op-le': '<=',\n      'op-lt': '<',\n      'op-ne': '!=',\n    } as const\n  )[opType];\n};\n\nexport const generateFlatAndOrList = (\n  expr: SpELProcessedExpression\n): (DefaultCombinatorName | SpELProcessedExpression)[] => {\n  const combinator = expr.type.slice(3) as DefaultCombinatorName;\n  const [left, right] = expr.children;\n  // SpEL AST has no parenthesis node, so `or` under `and` can only come from an explicit group\n  // (`and` binds tighter). Flattening it would lose the grouping.\n  const leftWasParenthesized = expr.type === 'op-and' && left.type === 'op-or';\n  if (!leftWasParenthesized && (left.type === 'op-and' || left.type === 'op-or')) {\n    return [...generateFlatAndOrList(left), combinator, right];\n  }\n  return [left, combinator, right];\n};\n\nexport const generateMixedAndOrList = (\n  expr: SpELOpAnd | SpELOpOr\n): (DefaultCombinatorName | SpELProcessedExpression | ('and' | SpELProcessedExpression)[])[] => {\n  const arr = generateFlatAndOrList(expr);\n  const returnArray: (\n    | DefaultCombinatorName\n    | SpELProcessedExpression\n    | ('and' | SpELProcessedExpression)[]\n  )[] = [];\n  let startIndex = 0;\n  for (let i = 0; i < arr.length; i += 2) {\n    if (arr[i + 1] === 'and') {\n      startIndex = i;\n      let j = 1;\n      while (arr[startIndex + j] === 'and') {\n        i += 2;\n        j += 2;\n      }\n      const tempAndArray = arr.slice(startIndex, i + 1) as ('and' | SpELProcessedExpression)[];\n      returnArray.push(tempAndArray);\n      i -= 2;\n    } else if (arr[i + 1] === 'or') {\n      if (i === 0 || i === arr.length - 3) {\n        if (i === 0 || arr[i - 1] === 'or') {\n          returnArray.push(arr[i]);\n        }\n        returnArray.push(arr[i + 1]);\n        if (i === arr.length - 3) {\n          returnArray.push(arr[i + 2]);\n        }\n      } else {\n        if (arr[i - 1] === 'and') {\n          returnArray.push(arr[i + 1]);\n        } else {\n          returnArray.push(arr[i], arr[i + 1]);\n        }\n      }\n    }\n  }\n  if (returnArray.length === 1 && Array.isArray(returnArray[0])) {\n    // If length is 1, then the only element is an AND array so just return that\n    return returnArray[0];\n  }\n  return returnArray;\n};\n","import { SpelExpressionEvaluator } from 'spel2js';\nimport type { Except } from 'type-fest';\nimport type {\n  DefaultCombinatorName,\n  DefaultOperatorName,\n  DefaultRuleGroupArray,\n  DefaultRuleGroupICArray,\n  DefaultRuleGroupType,\n  DefaultRuleGroupTypeAny,\n  DefaultRuleGroupTypeIC,\n  DefaultRuleType,\n  ExpressionNode,\n  ValueSource,\n} from '../../types';\nimport type { ParserCommonOptions } from '../../types/import';\nimport { joinWith } from '../arrayUtils';\nimport { isRuleGroup } from '../isRuleGroup';\nimport { fieldIsValidUtil, getFieldsArray } from '../parserUtils';\nimport { prepareRuleGroup } from '../prepareQueryObjects';\nimport type {\n  ParseSpELExpressionContext,\n  SpELExpressionNode,\n  SpELExpressionOperand,\n  SpELProcessedExpression,\n} from './types';\nimport {\n  generateFlatAndOrList,\n  generateMixedAndOrList,\n  isSpELBetweenFields,\n  isSpELBetweenValues,\n  isSpELExpressionOperand,\n  isSpELIdentifier,\n  isSpELOpAnd,\n  isSpELOpMatches,\n  isSpELOpOr,\n  isSpELPrimitive,\n  isSpELRelationOp,\n  normalizeOperator,\n  processCompiledExpression,\n} from './utils';\n\n/**\n * Options object for {@link parseSpEL!parseSpEL}.\n */\nexport interface ParseSpELOptions extends ParserCommonOptions {\n  /**\n   * Handler that converts a SpEL expression operand subtree into an {@link ExpressionNode}.\n   * Return `null` to reject (the rule is dropped). Supplied by `@react-querybuilder/expr`\n   * (`expressionParserSpEL`). When omitted, expression operands are ignored (rule dropped).\n   *\n   * Arithmetic infix operands and method/function invocations\n   * (`T(java.lang.Math).abs/min/max(...)`, `.toUpperCase()`/`.toLowerCase()`, and custom calls)\n   * are both supported. See {@link SpELExpressionOperand}.\n   */\n  getExpression?: (\n    node: SpELExpressionOperand,\n    ctx: ParseSpELExpressionContext\n  ) => ExpressionNode | null;\n}\n\n/**\n * Converts a SpEL string expression into a query suitable for the\n * {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\nfunction parseSpEL(spel: string): DefaultRuleGroupType;\n/**\n * Converts a SpEL string expression into a query suitable for the\n * {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\nfunction parseSpEL(\n  spel: string,\n  options: Except<ParseSpELOptions, 'independentCombinators'> & {\n    independentCombinators?: false;\n  }\n): DefaultRuleGroupType;\n/**\n * Converts a SpEL string expression into a query suitable for the\n * {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupTypeIC DefaultRuleGroupTypeIC}).\n */\nfunction parseSpEL(\n  spel: string,\n  options: Except<ParseSpELOptions, 'independentCombinators'> & {\n    independentCombinators: true;\n  }\n): DefaultRuleGroupTypeIC;\nfunction parseSpEL(spel: string, options: ParseSpELOptions = {}): DefaultRuleGroupTypeAny {\n  const { fields, independentCombinators, listsAsArrays, getExpression } = options;\n  const ic = !!independentCombinators;\n  const fieldsFlat = getFieldsArray(fields);\n\n  const fieldIsValid = (\n    fieldName: string,\n    operator: DefaultOperatorName,\n    subordinateFieldName?: string\n  ) =>\n    fieldIsValidUtil({\n      fieldName,\n      fieldsFlat,\n      operator,\n      subordinateFieldName,\n      getValueSources: options?.getValueSources,\n    });\n\n  const exprCtx: ParseSpELExpressionContext = {\n    fieldExists: fieldName => fieldsFlat.length === 0 || fieldsFlat.some(f => f.name === fieldName),\n  };\n\n  const emptyQuery: DefaultRuleGroupTypeAny = {\n    rules: [],\n    ...(ic ? {} : { combinator: 'and' }),\n  };\n\n  const parseProcessedSpEL = (\n    expr: SpELProcessedExpression,\n    processOpts: {\n      groupOnlyIfNecessary?: boolean;\n      forwardNegation?: boolean;\n    } = {}\n  ): DefaultRuleType | DefaultRuleGroupTypeAny | null => {\n    const { forwardNegation: _forwardedNegation, groupOnlyIfNecessary: _g } = processOpts;\n    if (expr.type === 'op-not') {\n      const negatedExpr = parseProcessedSpEL(expr.children[0]);\n      // v8 ignore else\n      if (negatedExpr) {\n        if (\n          !isRuleGroup(negatedExpr) &&\n          (negatedExpr.operator === 'contains' ||\n            negatedExpr.operator === 'beginsWith' ||\n            negatedExpr.operator === 'endsWith')\n        ) {\n          return {\n            ...negatedExpr,\n            operator: `doesNot${negatedExpr.operator[0].toUpperCase()}${negatedExpr.operator\n              .slice(1)\n              .replace('s', '')}` as DefaultOperatorName,\n          };\n        }\n        return ic\n          ? ({ rules: [negatedExpr], not: true } as DefaultRuleGroupTypeIC)\n          : ({\n              combinator: 'and',\n              rules: [negatedExpr],\n              not: true,\n            } as DefaultRuleGroupType);\n      }\n    } else if (isSpELOpAnd(expr) || isSpELOpOr(expr)) {\n      if (ic) {\n        const andOrList = generateFlatAndOrList(expr);\n        const rules = andOrList.map(v => {\n          if (typeof v === 'string') {\n            return v;\n          }\n          return parseProcessedSpEL(v);\n        });\n        // Bail out completely if any rules in the list were invalid\n        // so as not to return an incorrect and/or sequence\n        if (!rules.every(Boolean)) {\n          return null;\n        }\n        return {\n          rules: rules as DefaultRuleGroupICArray,\n        };\n      }\n      const andOrList = generateMixedAndOrList(expr);\n      const combinator = andOrList[1] as DefaultCombinatorName;\n      const filteredList = andOrList\n        .filter(v => Array.isArray(v) || (!!v && typeof v !== 'string' && 'type' in v))\n        .map(v =>\n          Array.isArray(v) ? v.filter(vf => !!v && typeof vf !== 'string' && 'type' in vf) : v\n        ) as (SpELProcessedExpression | SpELProcessedExpression[])[];\n      const rules = filteredList\n        .map((exp): DefaultRuleGroupType | DefaultRuleType | null => {\n          if (Array.isArray(exp)) {\n            return {\n              combinator: 'and',\n              rules: exp.map(e => parseProcessedSpEL(e)).filter(Boolean) as DefaultRuleGroupArray,\n            };\n          }\n          return parseProcessedSpEL(exp) as DefaultRuleType | DefaultRuleGroupType | null;\n        })\n        .filter(Boolean) as DefaultRuleGroupArray;\n      // v8 ignore else\n      if (rules.length > 0) {\n        return { combinator, rules };\n      }\n    } else if (isSpELOpMatches(expr)) {\n      const [left, right] = expr.children;\n      let field: string = '';\n      let regex: string = '';\n      let valueSource: ValueSource | undefined = undefined;\n      if (isSpELIdentifier(left)) {\n        field = left.identifier;\n        if (isSpELIdentifier(right)) {\n          regex = right.identifier;\n          valueSource = 'field';\n        } else {\n          // v8 ignore else\n          if (isSpELPrimitive(right)) {\n            regex = right.value;\n          }\n        }\n      } else {\n        // v8 ignore else\n        if (isSpELIdentifier(right) && isSpELPrimitive(left)) {\n          field = right.identifier;\n          regex = left.value;\n        }\n      }\n\n      if (/^(?!\\^).*?(?<!\\$)$/.test(regex)) {\n        // v8 ignore else\n        if (fieldIsValid(field, 'contains')) {\n          return {\n            field,\n            operator: 'contains',\n            value: regex,\n            ...(valueSource ? { valueSource } : {}),\n          };\n        }\n      } else {\n        if (/^\\^.*?(?<!\\$)$/.test(regex)) {\n          // v8 ignore else\n          if (fieldIsValid(field, 'beginsWith')) {\n            return {\n              field,\n              operator: 'beginsWith',\n              value: regex.replace(/^\\^/, ''),\n            };\n          }\n        } else {\n          // v8 ignore else\n          if (/^(?!\\^).*?\\$$/.test(regex)) {\n            // v8 ignore else\n            if (fieldIsValid(field, 'endsWith')) {\n              return {\n                field,\n                operator: 'endsWith',\n                value: regex.replace(/\\$$/, ''),\n              };\n            }\n          }\n        }\n      }\n    } else if (isSpELBetweenValues(expr) || isSpELBetweenFields(expr)) {\n      // oxlint-disable-next-line typescript/no-explicit-any\n      let values: [any, any] = [null, null];\n      let valueSource: ValueSource | undefined = undefined;\n      const [\n        { identifier: field },\n        {\n          children: [left, right],\n        },\n      ] = expr.children;\n\n      if (isSpELBetweenValues(expr)) {\n        values = [left.value, right.value];\n      } else {\n        values = [left.identifier, right.identifier];\n        valueSource = 'field';\n      }\n      // v8 ignore else\n      if (\n        field &&\n        values.every(v => fieldIsValid(field, 'between', valueSource === 'field' ? v : undefined))\n      ) {\n        const valueArray =\n          values[0] < values[1] || valueSource === 'field' ? values : [values[1], values[0]];\n        const value = listsAsArrays ? valueArray : joinWith(valueArray, ',');\n        return valueSource\n          ? { field, operator: 'between', value, valueSource }\n          : { field, operator: 'between', value };\n      }\n    } else if (isSpELRelationOp(expr)) {\n      let field: string | null = null;\n      // oxlint-disable-next-line typescript/no-explicit-any\n      let value: any = undefined;\n      let valueSource: ValueSource | undefined = undefined;\n      let flip = false;\n      const [left, right] = expr.children;\n\n      // Arithmetic and method/function expression operands (from `@react-querybuilder/expr`)\n      if (getExpression) {\n        const leftIsExpr = isSpELExpressionOperand(left);\n        const rightIsExpr = isSpELExpressionOperand(right);\n        if (leftIsExpr || rightIsExpr) {\n          const op = (flipOp: boolean) => normalizeOperator(expr.type, flipOp);\n          if (leftIsExpr && rightIsExpr) {\n            // expression <op> expression → both sides on lhs/value\n            const l = getExpression(left, exprCtx);\n            const r = getExpression(right, exprCtx);\n            return l && r\n              ? { field: '', operator: op(false), lhs: l, value: r, valueSource: 'expression' }\n              : null;\n          }\n          if (isSpELIdentifier(left) && rightIsExpr) {\n            // field <op> expression → rhs expression\n            const node = getExpression(right, exprCtx);\n            const f = left.identifier;\n            const operator = op(false);\n            return node && fieldIsValid(f, operator)\n              ? { field: f, operator, value: node, valueSource: 'expression' }\n              : null;\n          }\n          if (leftIsExpr && isSpELIdentifier(right)) {\n            // expression <op> field → flip to field <op> expression\n            const node = getExpression(left, exprCtx);\n            const f = right.identifier;\n            const operator = op(true);\n            return node && fieldIsValid(f, operator)\n              ? { field: f, operator, value: node, valueSource: 'expression' }\n              : null;\n          }\n          if (leftIsExpr && isSpELPrimitive(right)) {\n            // expression <op> literal → lhs = expression, literal value\n            const l = getExpression(left, exprCtx);\n            return l ? { field: '', operator: op(false), lhs: l, value: right.value } : null;\n          }\n          if (isSpELPrimitive(left)) {\n            // literal <op> expression → lhs = expression, flip operator\n            const r = getExpression(right, exprCtx);\n            return r ? { field: '', operator: op(true), lhs: r, value: left.value } : null;\n          }\n        }\n      }\n\n      if (isSpELIdentifier(left)) {\n        field = left.identifier;\n        if (isSpELIdentifier(right)) {\n          value = right.identifier;\n          valueSource = 'field';\n        } else if (isSpELPrimitive(right)) {\n          value = right.value;\n        }\n      } else {\n        // v8 ignore else\n        if (isSpELIdentifier(right) && isSpELPrimitive(left)) {\n          flip = true;\n          field = right.identifier;\n          value = left.value;\n        }\n      }\n      let operator = normalizeOperator(expr.type, flip);\n      if (value === null && (operator === '=' || operator === '!=')) {\n        operator = operator === '=' ? 'null' : 'notNull';\n      }\n      if (\n        field &&\n        fieldIsValid(field, operator, valueSource === 'field' ? value : undefined) &&\n        value !== undefined\n      ) {\n        return valueSource ? { field, operator, value, valueSource } : { field, operator, value };\n      }\n    }\n    return null;\n  };\n\n  const prepare = options.generateIDs ? prepareRuleGroup : <T>(g: T) => g;\n\n  let compiledSpEL: SpELExpressionNode;\n  try {\n    compiledSpEL = SpelExpressionEvaluator.compile(spel)._compiledExpression;\n  } catch {\n    return prepare(emptyQuery);\n  }\n\n  const processedSpEL = processCompiledExpression(compiledSpEL);\n\n  const result = parseProcessedSpEL(processedSpEL);\n  if (result) {\n    if (isRuleGroup(result)) {\n      return prepare(result);\n    }\n    return prepare({ rules: [result], ...(ic ? {} : { combinator: 'and' }) });\n  }\n\n  return prepare(emptyQuery);\n}\n\nexport { parseSpEL };\n"],"mappings":"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"}