{"version":3,"file":"utils.cjs","names":[],"sources":["../../src/store/utils.ts"],"sourcesContent":["/**\n * Tokenize a JSON path into parts.\n * @example\n * tokenizePath(\"metadata.title\") // -> [\"metadata\", \"title\"]\n * tokenizePath(\"chapters[*].content\") // -> [\"chapters[*]\", \"content\"]\n */\nexport function tokenizePath(path: string): string[] {\n  if (!path) {\n    return [];\n  }\n\n  const tokens: string[] = [];\n  let current: string[] = [];\n  let i = 0;\n\n  while (i < path.length) {\n    const char = path[i];\n\n    if (char === \"[\") {\n      // Handle array index\n      if (current.length) {\n        tokens.push(current.join(\"\"));\n        current = [];\n      }\n      let bracketCount = 1;\n      const indexChars = [\"[\"];\n      i += 1;\n      while (i < path.length && bracketCount > 0) {\n        if (path[i] === \"[\") {\n          bracketCount += 1;\n        } else if (path[i] === \"]\") {\n          bracketCount -= 1;\n        }\n        indexChars.push(path[i]);\n        i += 1;\n      }\n      tokens.push(indexChars.join(\"\"));\n      continue;\n    } else if (char === \"{\") {\n      // Handle multi-field selection\n      if (current.length) {\n        tokens.push(current.join(\"\"));\n        current = [];\n      }\n      let braceCount = 1;\n      const fieldChars = [\"{\"];\n      i += 1;\n      while (i < path.length && braceCount > 0) {\n        if (path[i] === \"{\") {\n          braceCount += 1;\n        } else if (path[i] === \"}\") {\n          braceCount -= 1;\n        }\n        fieldChars.push(path[i]);\n        i += 1;\n      }\n      tokens.push(fieldChars.join(\"\"));\n      continue;\n    } else if (char === \".\") {\n      // Handle regular field\n      if (current.length) {\n        tokens.push(current.join(\"\"));\n        current = [];\n      }\n    } else {\n      current.push(char);\n    }\n    i += 1;\n  }\n\n  if (current.length) {\n    tokens.push(current.join(\"\"));\n  }\n\n  return tokens;\n}\n\n/**\n * Represents the supported filter operators\n */\ntype FilterOperators = {\n  $eq?: unknown;\n  $ne?: unknown;\n  $gt?: unknown;\n  $gte?: unknown;\n  $lt?: unknown;\n  $lte?: unknown;\n  $in?: unknown[];\n  $nin?: unknown[];\n};\n\n/**\n * Type guard to check if an object is a FilterOperators\n */\nfunction isFilterOperators(obj: unknown): obj is FilterOperators {\n  return (\n    typeof obj === \"object\" &&\n    obj !== null &&\n    Object.keys(obj).every(\n      (key) =>\n        key === \"$eq\" ||\n        key === \"$ne\" ||\n        key === \"$gt\" ||\n        key === \"$gte\" ||\n        key === \"$lt\" ||\n        key === \"$lte\" ||\n        key === \"$in\" ||\n        key === \"$nin\"\n    )\n  );\n}\n\n/**\n * Compare values for filtering, supporting operator-based comparisons.\n */\nexport function compareValues(\n  itemValue: unknown,\n  filterValue: unknown\n): boolean {\n  if (isFilterOperators(filterValue)) {\n    const operators = Object.keys(filterValue).filter((k) => k.startsWith(\"$\"));\n    return operators.every((op) => {\n      const value = filterValue[op as keyof FilterOperators];\n      switch (op) {\n        case \"$eq\":\n          return itemValue === value;\n        case \"$ne\":\n          return itemValue !== value;\n        case \"$gt\":\n          return Number(itemValue) > Number(value);\n        case \"$gte\":\n          return Number(itemValue) >= Number(value);\n        case \"$lt\":\n          return Number(itemValue) < Number(value);\n        case \"$lte\":\n          return Number(itemValue) <= Number(value);\n        case \"$in\":\n          return Array.isArray(value) ? value.includes(itemValue) : false;\n        case \"$nin\":\n          return Array.isArray(value) ? !value.includes(itemValue) : true;\n        default:\n          return false;\n      }\n    });\n  }\n\n  // If no operators, do a direct comparison\n  return itemValue === filterValue;\n}\n\n/**\n * Extract text from a value at a specific JSON path.\n *\n * Supports:\n * - Simple paths: \"field1.field2\"\n * - Array indexing: \"[0]\", \"[*]\", \"[-1]\"\n * - Wildcards: \"*\"\n * - Multi-field selection: \"{field1,field2}\"\n * - Nested paths in multi-field: \"{field1,nested.field2}\"\n */\nexport function getTextAtPath(obj: unknown, path: string[] | string): string[] {\n  if (!path || path === \"$\") {\n    return [JSON.stringify(obj, null, 2)];\n  }\n  const tokens = Array.isArray(path) ? path : tokenizePath(path);\n\n  function extractFromObj(\n    obj: unknown,\n    tokens: string[],\n    pos: number\n  ): string[] {\n    if (pos >= tokens.length) {\n      if (\n        typeof obj === \"string\" ||\n        typeof obj === \"number\" ||\n        typeof obj === \"boolean\"\n      ) {\n        return [String(obj)];\n      }\n      if (obj === null || obj === undefined) {\n        return [];\n      }\n      if (Array.isArray(obj) || typeof obj === \"object\") {\n        return [JSON.stringify(obj, null, 2)];\n      }\n      return [];\n    }\n\n    const token = tokens[pos];\n    const results: string[] = [];\n    if (pos === 0 && token === \"$\") {\n      results.push(JSON.stringify(obj, null, 2));\n    }\n\n    if (token.startsWith(\"[\") && token.endsWith(\"]\")) {\n      if (!Array.isArray(obj)) return [];\n\n      const index = token.slice(1, -1);\n      if (index === \"*\") {\n        for (const item of obj) {\n          results.push(...extractFromObj(item, tokens, pos + 1));\n        }\n      } else {\n        try {\n          let idx = parseInt(index, 10);\n          if (idx < 0) {\n            idx = obj.length + idx;\n          }\n          if (idx >= 0 && idx < obj.length) {\n            results.push(...extractFromObj(obj[idx], tokens, pos + 1));\n          }\n        } catch {\n          return [];\n        }\n      }\n    } else if (token.startsWith(\"{\") && token.endsWith(\"}\")) {\n      if (typeof obj !== \"object\" || obj === null) return [];\n\n      const fields = token\n        .slice(1, -1)\n        .split(\",\")\n        .map((f) => f.trim());\n      for (const field of fields) {\n        const nestedTokens = tokenizePath(field);\n        if (nestedTokens.length) {\n          let currentObj = obj as Record<string, unknown> | undefined;\n          for (const nestedToken of nestedTokens) {\n            if (\n              currentObj &&\n              typeof currentObj === \"object\" &&\n              nestedToken in currentObj\n            ) {\n              currentObj = currentObj[nestedToken] as Record<string, unknown>;\n            } else {\n              currentObj = undefined;\n              break;\n            }\n          }\n          if (currentObj !== undefined) {\n            if (\n              typeof currentObj === \"string\" ||\n              typeof currentObj === \"number\" ||\n              typeof currentObj === \"boolean\"\n            ) {\n              results.push(String(currentObj));\n            } else if (\n              Array.isArray(currentObj) ||\n              typeof currentObj === \"object\"\n            ) {\n              results.push(JSON.stringify(currentObj, null, 2));\n            }\n          }\n        }\n      }\n    } else if (token === \"*\") {\n      if (Array.isArray(obj)) {\n        for (const item of obj) {\n          results.push(...extractFromObj(item, tokens, pos + 1));\n        }\n      } else if (typeof obj === \"object\" && obj !== null) {\n        for (const value of Object.values(obj)) {\n          results.push(...extractFromObj(value, tokens, pos + 1));\n        }\n      }\n    } else {\n      if (typeof obj === \"object\" && obj !== null && token in obj) {\n        results.push(\n          ...extractFromObj(\n            (obj as Record<string, unknown>)[token],\n            tokens,\n            pos + 1\n          )\n        );\n      }\n    }\n\n    return results;\n  }\n\n  return extractFromObj(obj, tokens, 0);\n}\n\n/**\n * Calculate cosine similarity between two vectors.\n */\nexport function cosineSimilarity(vector1: number[], vector2: number[]): number {\n  if (vector1.length !== vector2.length) {\n    throw new Error(\"Vectors must have the same length\");\n  }\n\n  const dotProduct = vector1.reduce((acc, val, i) => acc + val * vector2[i], 0);\n  const magnitude1 = Math.sqrt(\n    vector1.reduce((acc, val) => acc + val * val, 0)\n  );\n  const magnitude2 = Math.sqrt(\n    vector2.reduce((acc, val) => acc + val * val, 0)\n  );\n\n  if (magnitude1 === 0 || magnitude2 === 0) return 0;\n  return dotProduct / (magnitude1 * magnitude2);\n}\n"],"mappings":"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"}