UNPKG

@langchain/community

Version:
1 lines 12.4 kB
{"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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"}