{"version":3,"file":"supabase_utils.cjs","names":["StructuredQuery","Operation","Operators","Comparison","Comparators"],"sources":["../../src/structured_query/supabase_utils.ts"],"sourcesContent":["import {\n  Comparators,\n  Comparison,\n  Operation,\n  Operators,\n  StructuredQuery,\n} from \"@langchain/core/structured_query\";\nimport type {\n  SupabaseFilter,\n  SupabaseFilterRPCCall,\n  SupabaseMetadata,\n} from \"../vectorstores/supabase.js\";\n\ntype SupabaseFilterProps = keyof SupabaseFilter;\n\n/**\n * Utility class used to duplicate parameters for a proxy object,\n * specifically designed to work with `SupabaseFilter` objects. It\n * contains methods to handle different types of operations such as \"or\",\n * \"filter\", \"in\", \"contains\", \"textSearch\", \"match\", \"not\", and default\n * operations.\n */\nexport class ProxyParamsDuplicator {\n  duplicationAllowedOps: string[] = [\n    \"eq\",\n    \"neq\",\n    \"lt\",\n    \"lte\",\n    \"gt\",\n    \"gte\",\n    \"like\",\n    \"ilike\",\n    \"or\",\n    \"in\",\n    \"contains\",\n    \"match\",\n    \"not\",\n    \"textSearch\",\n    \"filter\",\n  ];\n\n  values: [string, string][] = [];\n\n  /**\n   * Creates a proxy handler for a `SupabaseFilter` object. The handler\n   * intercepts get operations and applies specific logic based on the\n   * property being accessed.\n   * @returns A proxy handler for a `SupabaseFilter` object.\n   */\n  buildProxyHandler() {\n    const proxyHandler: ProxyHandler<SupabaseFilter> = {\n      get: (target, prop, receiver) => {\n        if (typeof target[prop as SupabaseFilterProps] === \"function\") {\n          // oxlint-disable-next-line typescript/no-explicit-any\n          return (...args: any[]) => {\n            if (this.duplicationAllowedOps.includes(String(prop))) {\n              switch (String(prop)) {\n                case \"or\":\n                  // args[0]: filters, args[1]: { foreignTable }\n                  this.addOrClause(args[0], args[1]);\n                  break;\n                case \"filter\":\n                  // args[0]: column, args[1]: operator, args[2]: value\n                  this.addFilterClause(args[0], args[1], args[2]);\n                  break;\n                case \"in\":\n                  // args[0]: column, args[1]: values\n                  this.addInClause(args[0], args[1]);\n                  break;\n                case \"contains\":\n                  // args[0]: column, args[1]: value\n                  this.addContainsClause(args[0], args[1]);\n                  break;\n                case \"textSearch\":\n                  // args[0]: column, args[1]: query, args[2]: { config, type }\n                  this.addTextSearchClause(args[0], args[1], args[2]);\n                  break;\n                case \"match\":\n                  // args[0]: query\n                  this.addMatchClause(args[0]);\n                  break;\n                case \"not\":\n                  // args[0]: column, args[1]: operator, args[2]: value\n                  this.addNotClause(args[0], args[1], args[2]);\n                  break;\n                default:\n                  // args[0]: column, args[1]: value\n                  this.addDefaultOpClause(prop as string, args[0], args[1]);\n              }\n              return new Proxy(target, proxyHandler);\n            } else {\n              throw new Error(\n                \"Filter operation not supported for 'or' mergeFiltersOperator\"\n              );\n            }\n          };\n        } else {\n          return Reflect.get(target, prop, receiver);\n        }\n      },\n    };\n\n    return proxyHandler;\n  }\n\n  /**\n   * Removes type annotations from a value string.\n   * @param value The value string to clean.\n   * @returns The cleaned value string.\n   */\n  removeType(value: string) {\n    let cleanedValue = value;\n    if (cleanedValue.includes(\"::float\")) {\n      cleanedValue = cleanedValue.replace(\"::float\", \"\");\n    }\n    if (cleanedValue.includes(\"::int\")) {\n      cleanedValue = cleanedValue.replace(\"::int\", \"\");\n    }\n    return cleanedValue;\n  }\n\n  /**\n   * Adds a default operation clause to the values array.\n   * @param prop The operation property.\n   * @param column The column to apply the operation to.\n   * @param value The value for the operation.\n   */\n  addDefaultOpClause(prop: string, column: string, value: unknown) {\n    this.values.push([this.removeType(column), `${String(prop)}.${value}`]);\n  }\n\n  /**\n   * Adds an 'or' clause to the values array.\n   * @param filters The filters for the 'or' clause.\n   * @param foreignTable Optional foreign table for the 'or' clause.\n   */\n  addOrClause(\n    filters: string,\n    { foreignTable }: { foreignTable?: string } = {}\n  ) {\n    const key = foreignTable ? `${foreignTable}.or` : \"or\";\n    this.values.push([this.removeType(key), `(${filters})`]);\n  }\n\n  /**\n   * Adds a 'filter' clause to the values array.\n   * @param column The column to apply the filter to.\n   * @param operator The operator for the filter.\n   * @param value The value for the filter.\n   */\n  addFilterClause(column: string, operator: string, value: unknown) {\n    this.values.push([this.removeType(column), `${operator}.${value}`]);\n  }\n\n  /**\n   * Adds an 'in' clause to the values array.\n   * @param column The column to apply the 'in' clause to.\n   * @param values The values for the 'in' clause.\n   */\n  addInClause(column: string, values: unknown[]) {\n    const cleanedValues = values\n      .map((s) => {\n        if (typeof s === \"string\" && /[,()]/.test(s)) return `\"${s}\"`;\n        else return `${s}`;\n      })\n      .join(\",\");\n    this.values.push([this.removeType(column), `in.(${cleanedValues})`]);\n  }\n\n  /**\n   * Adds a 'contains' clause to the values array.\n   * @param column The column to apply the 'contains' clause to.\n   * @param value The value for the 'contains' clause.\n   */\n  addContainsClause(column: string, value: unknown) {\n    if (typeof value === \"string\") {\n      this.values.push([this.removeType(column), `cs.${value}`]);\n    } else if (Array.isArray(value)) {\n      this.values.push([this.removeType(column), `cs.{${value.join(\",\")}}`]);\n    } else {\n      this.values.push([\n        this.removeType(column),\n        `cs.${JSON.stringify(value)}`,\n      ]);\n    }\n  }\n\n  /**\n   * Adds a 'textSearch' clause to the values array.\n   * @param column The column to apply the 'textSearch' clause to.\n   * @param query The query for the 'textSearch' clause.\n   * @param config Optional configuration for the 'textSearch' clause.\n   * @param type Optional type for the 'textSearch' clause.\n   */\n  addTextSearchClause(\n    column: string,\n    query: string[],\n    {\n      config,\n      type,\n    }: { config?: string; type?: \"plain\" | \"phrase\" | \"websearch\" } = {}\n  ) {\n    let typePart = \"\";\n    if (type === \"plain\") {\n      typePart = \"pl\";\n    } else if (type === \"phrase\") {\n      typePart = \"ph\";\n    } else if (type === \"websearch\") {\n      typePart = \"w\";\n    }\n    const configPart = config === undefined ? \"\" : `(${config})`;\n    this.values.push([\n      this.removeType(column),\n      `${typePart}fts${configPart}.${query}`,\n    ]);\n  }\n\n  /**\n   * Adds a 'not' clause to the values array.\n   * @param column The column to apply the 'not' clause to.\n   * @param operator The operator for the 'not' clause.\n   * @param value The value for the 'not' clause.\n   */\n  addNotClause(column: string, operator: string, value: unknown) {\n    this.values.push([column, `not.${operator}.${value}`]);\n  }\n\n  /**\n   * Adds a 'match' clause to the values array.\n   * @param query The query for the 'match' clause.\n   */\n  addMatchClause(query: Record<string, unknown>) {\n    Object.entries(query).forEach(([column, value]) => {\n      this.values.push([column, `eq.${value}`]);\n    });\n  }\n\n  /**\n   * Returns the flattened parameters as a string.\n   * @returns The flattened parameters as a string.\n   */\n  flattenedParams() {\n    const mapped = this.values.map(([k, v]) => `${k}.${v}`);\n    if (mapped.length === 1) return mapped[0];\n    return `and(${mapped.join(\",\")})`;\n  }\n\n  /**\n   * Gets flattened parameters from a `SupabaseFilter` and a\n   * `SupabaseFilterRPCCall`.\n   * @param rpc The `SupabaseFilter` object.\n   * @param filter The `SupabaseFilterRPCCall` object.\n   * @returns The flattened parameters as a string.\n   */\n  static getFlattenedParams(\n    rpc: SupabaseFilter,\n    filter: SupabaseFilterRPCCall\n  ) {\n    const proxiedDuplicator = new ProxyParamsDuplicator();\n    const proxiedRpc = new Proxy(rpc, proxiedDuplicator.buildProxyHandler());\n    // eslint-disable-next-line no-void\n    void filter(proxiedRpc);\n    return proxiedDuplicator.flattenedParams();\n  }\n}\n\n/**\n * Converts a `SupabaseMetadata` object into a `StructuredQuery` object.\n * The function creates a new `StructuredQuery` object and uses the\n * `Operation` and `Comparison` classes to build the query.\n */\nexport function convertObjectFilterToStructuredQuery(\n  objFilter: SupabaseMetadata\n): StructuredQuery {\n  return new StructuredQuery(\n    \"\",\n    new Operation(\n      Operators.and,\n      Object.entries(objFilter).map(\n        ([column, value]) => new Comparison(Comparators.eq, column, value)\n      )\n    )\n  );\n}\n"],"mappings":"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"}