UNPKG

@langchain/community

Version:
1 lines • 13.1 kB
{"version":3,"file":"supabase_utils.cjs","names":["proxyHandler: ProxyHandler<SupabaseFilter>","value: string","prop: string","column: string","value: unknown","filters: string","operator: string","values: unknown[]","query: string[]","query: Record<string, unknown>","rpc: SupabaseFilter","filter: SupabaseFilterRPCCall","objFilter: SupabaseMetadata","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 // eslint-disable-next-line @typescript-eslint/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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"}