@cipherstash/stack 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -2
  3. package/dist/bin/stash.js +63 -45
  4. package/dist/bin/stash.js.map +1 -1
  5. package/dist/{chunk-5G4F4JJG.js → chunk-JLI27P46.js} +1 -1
  6. package/dist/chunk-JLI27P46.js.map +1 -0
  7. package/dist/{chunk-LHZ6KZIG.js → chunk-MW6D52V2.js} +42 -31
  8. package/dist/chunk-MW6D52V2.js.map +1 -0
  9. package/dist/{chunk-5DCT6YU2.js → chunk-OAPLZLR5.js} +7 -3
  10. package/dist/{chunk-5DCT6YU2.js.map → chunk-OAPLZLR5.js.map} +1 -1
  11. package/dist/{chunk-7XRPN2KX.js → chunk-TBAIVO6T.js} +26 -23
  12. package/dist/chunk-TBAIVO6T.js.map +1 -0
  13. package/dist/{client-D-ZH8SB2.d.cts → client-Bf0Xw2xo.d.cts} +19 -16
  14. package/dist/{client-BV9pXC-d.d.ts → client-Kfp8OsPB.d.ts} +19 -16
  15. package/dist/client.cjs +25 -22
  16. package/dist/client.cjs.map +1 -1
  17. package/dist/client.d.cts +2 -2
  18. package/dist/client.d.ts +2 -2
  19. package/dist/client.js +5 -5
  20. package/dist/drizzle/index.cjs +19 -16
  21. package/dist/drizzle/index.cjs.map +1 -1
  22. package/dist/drizzle/index.d.cts +5 -5
  23. package/dist/drizzle/index.d.ts +5 -5
  24. package/dist/drizzle/index.js +2 -2
  25. package/dist/drizzle/index.js.map +1 -1
  26. package/dist/dynamodb/index.cjs.map +1 -1
  27. package/dist/dynamodb/index.d.cts +10 -10
  28. package/dist/dynamodb/index.d.ts +10 -10
  29. package/dist/dynamodb/index.js.map +1 -1
  30. package/dist/identity/index.cjs +6 -2
  31. package/dist/identity/index.cjs.map +1 -1
  32. package/dist/identity/index.js +1 -1
  33. package/dist/index.cjs +67 -49
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +3 -3
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.js +7 -7
  38. package/dist/schema/index.cjs +31 -28
  39. package/dist/schema/index.cjs.map +1 -1
  40. package/dist/schema/index.d.cts +1 -1
  41. package/dist/schema/index.d.ts +1 -1
  42. package/dist/schema/index.js +11 -11
  43. package/dist/secrets/index.cjs +63 -45
  44. package/dist/secrets/index.cjs.map +1 -1
  45. package/dist/secrets/index.d.cts +1 -1
  46. package/dist/secrets/index.d.ts +1 -1
  47. package/dist/secrets/index.js +4 -4
  48. package/dist/secrets/index.js.map +1 -1
  49. package/dist/supabase/index.cjs +7 -7
  50. package/dist/supabase/index.cjs.map +1 -1
  51. package/dist/supabase/index.d.cts +3 -3
  52. package/dist/supabase/index.d.ts +3 -3
  53. package/dist/supabase/index.js +3 -3
  54. package/dist/supabase/index.js.map +1 -1
  55. package/dist/{types-public-Dfg-hkuQ.d.cts → types-public-0CzBV45X.d.cts} +70 -52
  56. package/dist/{types-public-Dfg-hkuQ.d.ts → types-public-0CzBV45X.d.ts} +70 -52
  57. package/dist/types-public.cjs.map +1 -1
  58. package/dist/types-public.d.cts +1 -1
  59. package/dist/types-public.d.ts +1 -1
  60. package/dist/types-public.js +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-5G4F4JJG.js.map +0 -1
  63. package/dist/chunk-7XRPN2KX.js.map +0 -1
  64. package/dist/chunk-LHZ6KZIG.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
2
  import { PgTable } from 'drizzle-orm/pg-core';
3
- import { e as encryptedTable, C as CastAs, M as MatchIndexOpts, T as TokenFilter } from '../types-public-Dfg-hkuQ.cjs';
4
- import { E as EncryptionClient } from '../client-D-ZH8SB2.cjs';
3
+ import { e as encryptedTable, C as CastAs, M as MatchIndexOpts, T as TokenFilter } from '../types-public-0CzBV45X.cjs';
4
+ import { E as EncryptionClient } from '../client-Bf0Xw2xo.cjs';
5
5
  import { SQLWrapper, SQL, exists, notExists, isNull, isNotNull, not, arrayContains, arrayContained, arrayOverlaps } from 'drizzle-orm';
6
6
  import 'zod';
7
7
  import 'evlog';
@@ -12,10 +12,10 @@ import '@byteslice/result';
12
12
  /**
13
13
  * Extracts an encryption schema from a Drizzle table definition.
14
14
  * This function identifies columns created with `encryptedType` and
15
- * builds a corresponding `ProtectTable` with `encryptedColumn` definitions.
15
+ * builds a corresponding `EncryptedTable` with `encryptedColumn` definitions.
16
16
  *
17
17
  * @param table - The Drizzle table definition
18
- * @returns A ProtectTable that can be used with encryption client initialization
18
+ * @returns A EncryptedTable that can be used with encryption client initialization
19
19
  *
20
20
  * @example
21
21
  * ```ts
@@ -28,7 +28,7 @@ import '@byteslice/result';
28
28
  * const client = await createEncryptionClient({ schemas: [encryptionSchema.build()] })
29
29
  * ```
30
30
  */
31
- declare function extractEncryptionSchema<T extends PgTable<any>>(table: T): ReturnType<typeof encryptedTable<Record<string, ProtectColumn>>>;
31
+ declare function extractEncryptionSchema<T extends PgTable<any>>(table: T): ReturnType<typeof encryptedTable<Record<string, EncryptedColumn>>>;
32
32
 
33
33
  /**
34
34
  * Custom error types for better debugging
@@ -1,7 +1,7 @@
1
1
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
2
  import { PgTable } from 'drizzle-orm/pg-core';
3
- import { e as encryptedTable, C as CastAs, M as MatchIndexOpts, T as TokenFilter } from '../types-public-Dfg-hkuQ.js';
4
- import { E as EncryptionClient } from '../client-BV9pXC-d.js';
3
+ import { e as encryptedTable, C as CastAs, M as MatchIndexOpts, T as TokenFilter } from '../types-public-0CzBV45X.js';
4
+ import { E as EncryptionClient } from '../client-Kfp8OsPB.js';
5
5
  import { SQLWrapper, SQL, exists, notExists, isNull, isNotNull, not, arrayContains, arrayContained, arrayOverlaps } from 'drizzle-orm';
6
6
  import 'zod';
7
7
  import 'evlog';
@@ -12,10 +12,10 @@ import '@byteslice/result';
12
12
  /**
13
13
  * Extracts an encryption schema from a Drizzle table definition.
14
14
  * This function identifies columns created with `encryptedType` and
15
- * builds a corresponding `ProtectTable` with `encryptedColumn` definitions.
15
+ * builds a corresponding `EncryptedTable` with `encryptedColumn` definitions.
16
16
  *
17
17
  * @param table - The Drizzle table definition
18
- * @returns A ProtectTable that can be used with encryption client initialization
18
+ * @returns A EncryptedTable that can be used with encryption client initialization
19
19
  *
20
20
  * @example
21
21
  * ```ts
@@ -28,7 +28,7 @@ import '@byteslice/result';
28
28
  * const client = await createEncryptionClient({ schemas: [encryptionSchema.build()] })
29
29
  * ```
30
30
  */
31
- declare function extractEncryptionSchema<T extends PgTable<any>>(table: T): ReturnType<typeof encryptedTable<Record<string, ProtectColumn>>>;
31
+ declare function extractEncryptionSchema<T extends PgTable<any>>(table: T): ReturnType<typeof encryptedTable<Record<string, EncryptedColumn>>>;
32
32
 
33
33
  /**
34
34
  * Custom error types for better debugging
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  queryTypes
3
- } from "../chunk-5G4F4JJG.js";
3
+ } from "../chunk-JLI27P46.js";
4
4
  import {
5
5
  encryptedColumn,
6
6
  encryptedTable
7
- } from "../chunk-7XRPN2KX.js";
7
+ } from "../chunk-TBAIVO6T.js";
8
8
 
9
9
  // src/drizzle/index.ts
10
10
  import { customType } from "drizzle-orm/pg-core";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/drizzle/index.ts","../../src/drizzle/schema-extraction.ts","../../src/drizzle/operators.ts"],"sourcesContent":["import type { CastAs, MatchIndexOpts, TokenFilter } from '@/schema'\nimport { customType } from 'drizzle-orm/pg-core'\n\nexport type { CastAs, MatchIndexOpts, TokenFilter }\n\n/**\n * Configuration for encrypted column indexes and data types\n */\nexport type EncryptedColumnConfig = {\n /**\n * Data type for the column (default: 'string')\n */\n dataType?: CastAs\n /**\n * Enable free text search. Can be a boolean for default options, or an object for custom configuration.\n */\n freeTextSearch?: boolean | MatchIndexOpts\n /**\n * Enable equality index. Can be a boolean for default options, or an array of token filters.\n */\n equality?: boolean | TokenFilter[]\n /**\n * Enable order and range index for sorting and range queries.\n */\n orderAndRange?: boolean\n /**\n * Enable searchable JSON index for JSONB path queries.\n * Requires dataType: 'json'.\n */\n searchableJson?: boolean\n}\n\n/**\n * Map to store configuration for encrypted columns\n * Keyed by column name (the name passed to encryptedType)\n */\nconst columnConfigMap = new Map<\n string,\n EncryptedColumnConfig & { name: string }\n>()\n\n/**\n * Creates an encrypted column type for Drizzle ORM with configurable searchable encryption options.\n *\n * When data is encrypted, the actual stored value is an [EQL v2](/docs/reference/eql) encrypted composite type which includes any searchable encryption indexes defined for the column.\n * Importantly, the original data type is not known until it is decrypted. Therefore, this function allows specifying\n * the original data type via the `dataType` option in the configuration.\n * This ensures that when data is decrypted, it can be correctly interpreted as the intended TypeScript type.\n *\n * @typeParam TData - The TypeScript type of the data stored in the column\n * @param name - The column name in the database\n * @param config - Optional configuration for data type and searchable encryption indexes\n * @returns A Drizzle column type that can be used in pgTable definitions\n *\n * ## Searchable Encryption Options\n *\n * - `dataType`: Specifies the original data type of the column (e.g., 'string', 'number', 'json'). Default is 'string'.\n * - `freeTextSearch`: Enables free text search index. Can be a boolean for default options, or an object for custom configuration.\n * - `equality`: Enables equality index. Can be a boolean for default options, or an array of token filters.\n * - `orderAndRange`: Enables order and range index for sorting and range queries.\n * - `searchableJson`: Enables searchable JSON index for JSONB path queries on encrypted JSON columns.\n *\n * See {@link EncryptedColumnConfig}.\n *\n * @example\n * Defining a drizzle table schema for postgres table with encrypted columns.\n *\n * ```typescript\n * import { pgTable, integer, timestamp } from 'drizzle-orm/pg-core'\n * import { encryptedType } from '@cipherstash/stack/drizzle'\n *\n * const users = pgTable('users', {\n * email: encryptedType('email', {\n * freeTextSearch: true,\n * equality: true,\n * orderAndRange: true,\n * }),\n * age: encryptedType('age', {\n * dataType: 'number',\n * equality: true,\n * orderAndRange: true,\n * }),\n * profile: encryptedType('profile', {\n * dataType: 'json',\n * }),\n * })\n * ```\n */\nexport const encryptedType = <TData>(\n name: string,\n config?: EncryptedColumnConfig,\n) => {\n // Create the Drizzle custom type\n const customColumnType = customType<{ data: TData; driverData: string }>({\n dataType() {\n return 'eql_v2_encrypted'\n },\n toDriver(value: TData): string {\n const jsonStr = JSON.stringify(value)\n const escaped = jsonStr.replace(/\"/g, '\"\"')\n return `(\"${escaped}\")`\n },\n fromDriver(value: string): TData {\n const parseComposite = (str: string) => {\n if (!str || str === '') return null\n\n const trimmed = str.trim()\n\n if (trimmed.startsWith('(') && trimmed.endsWith(')')) {\n let inner = trimmed.slice(1, -1)\n inner = inner.replace(/\"\"/g, '\"')\n\n if (inner.startsWith('\"') && inner.endsWith('\"')) {\n const stripped = inner.slice(1, -1)\n return JSON.parse(stripped)\n }\n\n if (inner.startsWith('{') || inner.startsWith('[')) {\n return JSON.parse(inner)\n }\n\n return inner\n }\n\n return JSON.parse(str)\n }\n\n return parseComposite(value) as TData\n },\n })\n\n // Create the column instance\n const column = customColumnType(name)\n\n // Store configuration keyed by column name\n // This allows us to look it up during schema extraction\n const fullConfig: EncryptedColumnConfig & { name: string } = {\n name,\n ...config,\n }\n\n // Store in Map keyed by column name (will be looked up during extraction)\n columnConfigMap.set(name, fullConfig)\n\n // Also store on property for immediate access (before pgTable processes it)\n // We need to use any here because Drizzle columns don't have a type for custom properties\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle columns don't expose custom property types\n ;(column as any)._encryptionConfig = fullConfig\n\n return column\n}\n\n/**\n * Get configuration for an encrypted column by checking if it's an encrypted type\n * and looking up the config by column name\n * @internal\n */\nexport function getEncryptedColumnConfig(\n columnName: string,\n column: unknown,\n): (EncryptedColumnConfig & { name: string }) | undefined {\n // Check if this is an encrypted column\n if (column && typeof column === 'object') {\n // We need to use any here to access Drizzle column properties\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle column types don't expose all properties\n const columnAny = column as any\n\n // Check if it's an encrypted column by checking sqlName or dataType\n // After pgTable processes it, sqlName will be 'eql_v2_encrypted'\n const isEncrypted =\n columnAny.sqlName === 'eql_v2_encrypted' ||\n columnAny.dataType === 'eql_v2_encrypted' ||\n (columnAny.dataType &&\n typeof columnAny.dataType === 'function' &&\n columnAny.dataType() === 'eql_v2_encrypted')\n\n if (isEncrypted) {\n // Try to get config from property (if still there)\n if (columnAny._encryptionConfig) {\n return columnAny._encryptionConfig\n }\n\n // Look up config by column name (the name passed to encryptedType)\n // The column.name should match what was passed to encryptedType\n const lookupName = columnAny.name || columnName\n return columnConfigMap.get(lookupName)\n }\n }\n return undefined\n}\n\n/**\n * Extract a CipherStash encryption schema from a Drizzle table definition.\n *\n * Inspects columns created with {@link encryptedType} and builds the equivalent\n * `encryptedTable` / `encryptedColumn` schema automatically.\n */\nexport { extractEncryptionSchema } from './schema-extraction.js'\n\n/**\n * Create Drizzle query operators (`eq`, `lt`, `gt`, etc.) that work with\n * encrypted columns. The returned operators encrypt query values before\n * passing them to Drizzle, enabling searchable encryption in standard\n * Drizzle queries.\n */\nexport {\n createEncryptionOperators,\n EncryptionOperatorError,\n EncryptionConfigError,\n} from './operators.js'\n","import { type ProtectColumn, encryptedColumn, encryptedTable } from '@/schema'\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport { getEncryptedColumnConfig } from './index.js'\n\n/**\n * Extracts an encryption schema from a Drizzle table definition.\n * This function identifies columns created with `encryptedType` and\n * builds a corresponding `ProtectTable` with `encryptedColumn` definitions.\n *\n * @param table - The Drizzle table definition\n * @returns A ProtectTable that can be used with encryption client initialization\n *\n * @example\n * ```ts\n * const drizzleUsersTable = pgTable('users', {\n * email: encryptedType('email', { freeTextSearch: true, equality: true }),\n * age: encryptedType('age', { dataType: 'number', orderAndRange: true }),\n * })\n *\n * const encryptionSchema = extractEncryptionSchema(drizzleUsersTable)\n * const client = await createEncryptionClient({ schemas: [encryptionSchema.build()] })\n * ```\n */\n// We use any for the PgTable generic because we need to access Drizzle's internal properties\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle table types don't expose Symbol properties\nexport function extractEncryptionSchema<T extends PgTable<any>>(\n table: T,\n): ReturnType<typeof encryptedTable<Record<string, ProtectColumn>>> {\n // Drizzle tables store the name in a Symbol property\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle tables don't expose Symbol properties in types\n const tableName = (table as any)[Symbol.for('drizzle:Name')] as\n | string\n | undefined\n if (!tableName) {\n throw new Error(\n 'Unable to extract table name from Drizzle table. Ensure you are using a table created with pgTable().',\n )\n }\n\n const columns: Record<string, ProtectColumn> = {}\n\n // Iterate through table columns\n for (const [columnName, column] of Object.entries(table)) {\n // Skip if it's not a column (could be methods or other properties)\n if (typeof column !== 'object' || column === null) {\n continue\n }\n\n // Check if this column has encrypted configuration\n const config = getEncryptedColumnConfig(columnName, column)\n\n if (config) {\n // Extract the actual column name from the column object (not the schema key)\n // Drizzle columns have a 'name' property that contains the actual database column name\n const actualColumnName = column.name || config.name\n\n // This is an encrypted column - build encryptedColumn using the actual column name\n const csCol = encryptedColumn(actualColumnName)\n\n // Apply data type\n if (config.dataType && config.dataType !== 'string') {\n csCol.dataType(config.dataType)\n }\n\n // Apply indexes based on configuration\n if (config.orderAndRange) {\n csCol.orderAndRange()\n }\n\n if (config.equality) {\n if (Array.isArray(config.equality)) {\n // Custom token filters\n csCol.equality(config.equality)\n } else {\n // Default equality (boolean true)\n csCol.equality()\n }\n }\n\n if (config.freeTextSearch) {\n if (typeof config.freeTextSearch === 'object') {\n // Custom match options\n csCol.freeTextSearch(config.freeTextSearch)\n } else {\n // Default freeTextSearch (boolean true)\n csCol.freeTextSearch()\n }\n }\n\n if (config.searchableJson) {\n if (config.dataType !== 'json') {\n throw new Error(\n `Column \"${columnName}\" has searchableJson enabled but dataType is \"${config.dataType ?? 'string'}\". searchableJson requires dataType: 'json'.`,\n )\n }\n csCol.searchableJson()\n }\n\n columns[actualColumnName] = csCol\n }\n }\n\n if (Object.keys(columns).length === 0) {\n throw new Error(\n `No encrypted columns found in table \"${tableName}\". Use encryptedType() to define encrypted columns.`,\n )\n }\n\n return encryptedTable(tableName, columns)\n}\n","import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectColumn, ProtectTable, ProtectTableColumn } from '@/schema'\nimport { type QueryTypeName, queryTypes } from '@/types'\nimport {\n type SQL,\n type SQLWrapper,\n and,\n arrayContained,\n arrayContains,\n arrayOverlaps,\n asc,\n between,\n desc,\n eq,\n exists,\n gt,\n gte,\n ilike,\n inArray,\n isNotNull,\n isNull,\n like,\n lt,\n lte,\n ne,\n not,\n notBetween,\n notExists,\n notIlike,\n notInArray,\n or,\n} from 'drizzle-orm'\nimport { bindIfParam, sql } from 'drizzle-orm'\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport type { EncryptedColumnConfig } from './index.js'\nimport { getEncryptedColumnConfig } from './index.js'\nimport { extractEncryptionSchema } from './schema-extraction.js'\n\n// ============================================================================\n// Type Definitions and Type Guards\n// ============================================================================\n\n/**\n * Branded type for Drizzle table with encrypted columns\n */\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle table types don't expose Symbol properties\ntype EncryptedDrizzleTable = PgTable<any> & {\n readonly __isEncryptedTable?: true\n}\n\n/**\n * Type guard to check if a value is a Drizzle SQLWrapper\n */\nfunction isSQLWrapper(value: unknown): value is SQLWrapper {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'sql' in value &&\n typeof (value as { sql: unknown }).sql !== 'undefined'\n )\n}\n\n/**\n * Type guard to check if a value is a Drizzle table\n */\nfunction isPgTable(value: unknown): value is EncryptedDrizzleTable {\n return (\n typeof value === 'object' &&\n value !== null &&\n Symbol.for('drizzle:Name') in value\n )\n}\n\n/**\n * Custom error types for better debugging\n */\nexport class EncryptionOperatorError extends Error {\n constructor(\n message: string,\n public readonly context?: {\n tableName?: string\n columnName?: string\n operator?: string\n },\n ) {\n super(message)\n this.name = 'EncryptionOperatorError'\n }\n}\n\nexport class EncryptionConfigError extends EncryptionOperatorError {\n constructor(message: string, context?: EncryptionOperatorError['context']) {\n super(message, context)\n this.name = 'EncryptionConfigError'\n }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Helper to extract table name from a Drizzle table\n */\nfunction getDrizzleTableName(drizzleTable: unknown): string | undefined {\n if (!isPgTable(drizzleTable)) {\n return undefined\n }\n // Access Symbol property using Record type to avoid indexing errors\n const tableWithSymbol = drizzleTable as unknown as Record<\n symbol,\n string | undefined\n >\n return tableWithSymbol[Symbol.for('drizzle:Name')]\n}\n\n/**\n * Helper to get the drizzle table from a drizzle column\n */\nfunction getDrizzleTableFromColumn(drizzleColumn: SQLWrapper): unknown {\n const column = drizzleColumn as unknown as Record<string, unknown>\n return column.table as unknown\n}\n\n/**\n * Helper to extract encrypted table from a drizzle column by deriving it from the column's parent table\n */\nfunction getEncryptedTableFromColumn(\n drizzleColumn: SQLWrapper,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): ProtectTable<ProtectTableColumn> | undefined {\n const drizzleTable = getDrizzleTableFromColumn(drizzleColumn)\n if (!drizzleTable) {\n return undefined\n }\n\n const tableName = getDrizzleTableName(drizzleTable)\n if (!tableName) {\n return undefined\n }\n\n // Check cache first\n let encryptedTable = tableCache.get(tableName)\n if (encryptedTable) {\n return encryptedTable\n }\n\n // Extract encryption schema from drizzle table and cache it\n try {\n // biome-ignore lint/suspicious/noExplicitAny: PgTable type doesn't expose all needed properties\n encryptedTable = extractEncryptionSchema(drizzleTable as PgTable<any>)\n tableCache.set(tableName, encryptedTable)\n return encryptedTable\n } catch {\n // Table doesn't have encrypted columns or extraction failed\n return undefined\n }\n}\n\n/**\n * Helper to get the encrypted column definition for a Drizzle column from the encrypted table\n */\nfunction getEncryptedColumn(\n drizzleColumn: SQLWrapper,\n encryptedTable: ProtectTable<ProtectTableColumn>,\n): ProtectColumn | undefined {\n const column = drizzleColumn as unknown as Record<string, unknown>\n const columnName = column.name as string | undefined\n if (!columnName) {\n return undefined\n }\n\n const tableRecord = encryptedTable as unknown as Record<string, unknown>\n return tableRecord[columnName] as ProtectColumn | undefined\n}\n\n/**\n * Column metadata extracted from a Drizzle column\n */\ninterface ColumnInfo {\n readonly encryptedColumn: ProtectColumn | undefined\n readonly config: (EncryptedColumnConfig & { name: string }) | undefined\n readonly encryptedTable: ProtectTable<ProtectTableColumn> | undefined\n readonly columnName: string\n readonly tableName: string | undefined\n}\n\n/**\n * Helper to get the encrypted column and column config for a Drizzle column\n * If encryptedTable is not provided, it will be derived from the column\n */\nfunction getColumnInfo(\n drizzleColumn: SQLWrapper,\n encryptedTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): ColumnInfo {\n const column = drizzleColumn as unknown as Record<string, unknown>\n const columnName = (column.name as string | undefined) || 'unknown'\n\n // If encryptedTable not provided, try to derive it from the column\n let resolvedTable = encryptedTable\n if (!resolvedTable) {\n resolvedTable = getEncryptedTableFromColumn(drizzleColumn, tableCache)\n }\n\n const drizzleTable = getDrizzleTableFromColumn(drizzleColumn)\n const tableName = getDrizzleTableName(drizzleTable)\n\n if (!resolvedTable) {\n // Column is not from an encrypted table\n const config = getEncryptedColumnConfig(columnName, drizzleColumn)\n return {\n encryptedColumn: undefined,\n config,\n encryptedTable: undefined,\n columnName,\n tableName,\n }\n }\n\n const encryptedColumn = getEncryptedColumn(drizzleColumn, resolvedTable)\n const config = getEncryptedColumnConfig(columnName, drizzleColumn)\n\n return {\n encryptedColumn,\n config,\n encryptedTable: resolvedTable,\n columnName,\n tableName,\n }\n}\n\n/**\n * Helper to convert a value to plaintext format\n */\nfunction toPlaintext(value: unknown): string | number {\n if (typeof value === 'boolean') {\n return value ? 1 : 0\n }\n if (typeof value === 'string' || typeof value === 'number') {\n return value\n }\n if (value instanceof Date) {\n return value.toISOString()\n }\n return String(value)\n}\n\n/**\n * Value to encrypt with its associated column\n */\ninterface ValueToEncrypt {\n readonly value: string | number\n readonly column: SQLWrapper\n readonly columnInfo: ColumnInfo\n readonly queryType?: QueryTypeName\n readonly originalIndex: number\n}\n\n/**\n * Helper to encrypt multiple values for use in a query\n * Returns an array of encrypted search terms or original values if not encrypted\n */\nasync function encryptValues(\n encryptionClient: EncryptionClient,\n values: Array<{\n value: unknown\n column: SQLWrapper\n queryType?: QueryTypeName\n }>,\n encryptedTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<unknown[]> {\n if (values.length === 0) {\n return []\n }\n\n // Single pass: collect values to encrypt with their metadata\n const valuesToEncrypt: ValueToEncrypt[] = []\n const results: unknown[] = new Array(values.length)\n\n for (let i = 0; i < values.length; i++) {\n const { value, column, queryType } = values[i]\n const columnInfo = getColumnInfo(column, encryptedTable, tableCache)\n\n if (\n !columnInfo.encryptedColumn ||\n !columnInfo.config ||\n !columnInfo.encryptedTable\n ) {\n // Column is not encrypted, return value as-is\n results[i] = value\n continue\n }\n\n const plaintextValue = toPlaintext(value)\n valuesToEncrypt.push({\n value: plaintextValue,\n column,\n columnInfo,\n queryType,\n originalIndex: i,\n })\n }\n\n if (valuesToEncrypt.length === 0) {\n return results\n }\n\n // Group values by column to batch encrypt with same column/table\n const columnGroups = new Map<\n string,\n {\n column: ProtectColumn\n table: ProtectTable<ProtectTableColumn>\n columnName: string\n values: Array<{\n value: string | number\n index: number\n queryType?: QueryTypeName\n }>\n resultIndices: number[]\n }\n >()\n\n let valueIndex = 0\n for (const {\n value,\n columnInfo,\n queryType,\n originalIndex,\n } of valuesToEncrypt) {\n // Safe access with validation - we know these exist from earlier checks\n if (\n !columnInfo.config ||\n !columnInfo.encryptedColumn ||\n !columnInfo.encryptedTable\n ) {\n continue\n }\n\n const columnName = columnInfo.config.name\n const groupKey = `${columnInfo.tableName ?? 'unknown'}/${columnName}`\n let group = columnGroups.get(groupKey)\n if (!group) {\n group = {\n column: columnInfo.encryptedColumn,\n table: columnInfo.encryptedTable,\n columnName,\n values: [],\n resultIndices: [],\n }\n columnGroups.set(groupKey, group)\n }\n group.values.push({ value, index: valueIndex++, queryType })\n group.resultIndices.push(originalIndex)\n }\n\n // Encrypt all values for each column in batches\n for (const [, group] of columnGroups) {\n const { columnName } = group\n try {\n const terms = group.values.map((v) => ({\n value: v.value,\n column: group.column,\n table: group.table,\n queryType: v.queryType,\n }))\n\n const encryptedTerms = await encryptionClient.encryptQuery(terms)\n\n if (encryptedTerms.failure) {\n throw new EncryptionOperatorError(\n `Failed to encrypt query terms for column \"${columnName}\": ${encryptedTerms.failure.message}`,\n { columnName },\n )\n }\n\n // Map results back to original indices\n for (let i = 0; i < group.values.length; i++) {\n const resultIndex = group.resultIndices[i] ?? -1\n if (resultIndex >= 0 && resultIndex < results.length) {\n results[resultIndex] = encryptedTerms.data[i]\n }\n }\n } catch (error) {\n if (error instanceof EncryptionOperatorError) {\n throw error\n }\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n throw new EncryptionOperatorError(\n `Unexpected error encrypting values for column \"${columnName}\": ${errorMessage}`,\n { columnName },\n )\n }\n }\n\n return results\n}\n\n/**\n * Helper to encrypt a single value for use in a query\n * Returns the encrypted search term or the original value if not encrypted\n */\nasync function encryptValue(\n encryptionClient: EncryptionClient,\n value: unknown,\n drizzleColumn: SQLWrapper,\n encryptedTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n queryType?: QueryTypeName,\n): Promise<unknown> {\n const results = await encryptValues(\n encryptionClient,\n [{ value, column: drizzleColumn, queryType }],\n encryptedTable,\n tableCache,\n )\n return results[0]\n}\n\n// ============================================================================\n// Lazy Operator Pattern\n// ============================================================================\n\n/**\n * Simplified lazy operator that defers encryption until awaited or batched\n */\ninterface LazyOperator {\n readonly __isLazyOperator: true\n readonly operator: string\n readonly queryType?: QueryTypeName\n readonly left: SQLWrapper\n readonly right: unknown\n readonly min?: unknown\n readonly max?: unknown\n readonly needsEncryption: boolean\n readonly columnInfo: ColumnInfo\n execute(\n encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ): SQL\n}\n\n/**\n * Type guard for lazy operators\n */\nfunction isLazyOperator(value: unknown): value is LazyOperator {\n return (\n typeof value === 'object' &&\n value !== null &&\n '__isLazyOperator' in value &&\n (value as LazyOperator).__isLazyOperator === true\n )\n}\n\n/**\n * Creates a lazy operator that defers execution\n */\nfunction createLazyOperator(\n operator: string,\n left: SQLWrapper,\n right: unknown,\n execute: (\n encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ) => SQL,\n needsEncryption: boolean,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n min?: unknown,\n max?: unknown,\n queryType?: QueryTypeName,\n): LazyOperator & Promise<SQL> {\n let resolvedSQL: SQL | undefined\n let encryptionPromise: Promise<SQL> | undefined\n\n const lazyOp: LazyOperator = {\n __isLazyOperator: true,\n operator,\n queryType,\n left,\n right,\n min,\n max,\n needsEncryption,\n columnInfo,\n execute,\n }\n\n // Create a promise that will be resolved when encryption completes\n const promise = new Promise<SQL>((resolve, reject) => {\n // Auto-execute when awaited directly\n queueMicrotask(async () => {\n if (resolvedSQL !== undefined) {\n resolve(resolvedSQL)\n return\n }\n\n try {\n if (!encryptionPromise) {\n encryptionPromise = executeLazyOperatorDirect(\n lazyOp,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n const sql = await encryptionPromise\n resolvedSQL = sql\n resolve(sql)\n } catch (error) {\n reject(error)\n }\n })\n })\n\n // Attach lazy operator properties to the promise\n return Object.assign(promise, lazyOp)\n}\n\n/**\n * Executes a lazy operator with pre-encrypted values (used in batched mode)\n */\nasync function executeLazyOperator(\n lazyOp: LazyOperator,\n encryptedValues?: { value: unknown; encrypted: unknown }[],\n): Promise<SQL> {\n if (!lazyOp.needsEncryption) {\n return lazyOp.execute(lazyOp.right)\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n // Between operator - use provided encrypted values\n let encryptedMin: unknown\n let encryptedMax: unknown\n\n if (encryptedValues && encryptedValues.length >= 2) {\n encryptedMin = encryptedValues[0]?.encrypted\n encryptedMax = encryptedValues[1]?.encrypted\n } else {\n throw new EncryptionOperatorError(\n 'Between operator requires both min and max encrypted values',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n if (encryptedMin === undefined || encryptedMax === undefined) {\n throw new EncryptionOperatorError(\n 'Between operator requires both min and max values to be encrypted',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n return lazyOp.execute(undefined, encryptedMin, encryptedMax)\n }\n\n // Single value operator\n let encrypted: unknown\n\n if (encryptedValues && encryptedValues.length > 0) {\n encrypted = encryptedValues[0]?.encrypted\n } else {\n throw new EncryptionOperatorError(\n 'Operator requires encrypted value but none provided',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n 'Encryption failed or value was not encrypted',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n return lazyOp.execute(encrypted)\n}\n\n/**\n * Executes a lazy operator directly by encrypting values on demand\n * Used when operator is awaited directly (not batched)\n */\nasync function executeLazyOperatorDirect(\n lazyOp: LazyOperator,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<SQL> {\n if (!lazyOp.needsEncryption) {\n return lazyOp.execute(lazyOp.right)\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n // Between operator - encrypt min and max\n const [encryptedMin, encryptedMax] = await encryptValues(\n encryptionClient,\n [\n { value: lazyOp.min, column: lazyOp.left, queryType: lazyOp.queryType },\n { value: lazyOp.max, column: lazyOp.left, queryType: lazyOp.queryType },\n ],\n defaultTable,\n tableCache,\n )\n return lazyOp.execute(undefined, encryptedMin, encryptedMax)\n }\n\n // Single value operator\n const encrypted = await encryptValue(\n encryptionClient,\n lazyOp.right,\n lazyOp.left,\n defaultTable,\n tableCache,\n lazyOp.queryType,\n )\n\n return lazyOp.execute(encrypted)\n}\n\n// ============================================================================\n// Operator Factory Functions\n// ============================================================================\n\n/**\n * Creates a comparison operator (eq, ne, gt, gte, lt, lte)\n */\nfunction createComparisonOperator(\n operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n // Operators requiring orderAndRange index\n const requiresOrderAndRange = ['gt', 'gte', 'lt', 'lte'].includes(operator)\n\n if (requiresOrderAndRange) {\n if (!config?.orderAndRange) {\n // Return regular Drizzle operator for non-encrypted columns\n switch (operator) {\n case 'gt':\n return gt(left, right)\n case 'gte':\n return gte(left, right)\n case 'lt':\n return lt(left, right)\n case 'lte':\n return lte(left, right)\n }\n }\n\n // This will be replaced with encrypted value in executeLazyOperator\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n return sql`eql_v2.${sql.raw(operator)}(${left}, ${bindIfParam(encrypted, left)})`\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.orderAndRange,\n ) as Promise<SQL>\n }\n\n // Equality operators (eq, ne)\n const requiresEquality = ['eq', 'ne'].includes(operator)\n\n if (requiresEquality && config?.equality) {\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n return operator === 'eq' ? eq(left, encrypted) : ne(left, encrypted)\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.equality,\n ) as Promise<SQL>\n }\n\n // Fallback to regular Drizzle operators\n return operator === 'eq' ? eq(left, right) : ne(left, right)\n}\n\n/**\n * Creates a range operator (between, notBetween)\n */\nfunction createRangeOperator(\n operator: 'between' | 'notBetween',\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n if (!config?.orderAndRange) {\n return operator === 'between'\n ? between(left, min, max)\n : notBetween(left, min, max)\n }\n\n const executeFn = (\n _encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ) => {\n if (encryptedMin === undefined || encryptedMax === undefined) {\n throw new EncryptionOperatorError(\n `${operator} operator requires both min and max values`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const rangeCondition = sql`eql_v2.gte(${left}, ${bindIfParam(encryptedMin, left)}) AND eql_v2.lte(${left}, ${bindIfParam(encryptedMax, left)})`\n\n return operator === 'between'\n ? rangeCondition\n : sql`NOT (${rangeCondition})`\n }\n\n return createLazyOperator(\n operator,\n left,\n undefined,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n min,\n max,\n queryTypes.orderAndRange,\n ) as Promise<SQL>\n}\n\n/**\n * Creates a text search operator (like, ilike, notIlike)\n */\nfunction createTextSearchOperator(\n operator: 'like' | 'ilike' | 'notIlike',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n if (!config?.freeTextSearch) {\n // Cast to satisfy TypeScript\n const rightValue = right as string | SQLWrapper\n switch (operator) {\n case 'like':\n return like(left as Parameters<typeof like>[0], rightValue)\n case 'ilike':\n return ilike(left as Parameters<typeof ilike>[0], rightValue)\n case 'notIlike':\n return notIlike(left as Parameters<typeof notIlike>[0], rightValue)\n }\n }\n\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const sqlFn = sql`eql_v2.${sql.raw(operator === 'notIlike' ? 'ilike' : operator)}(${left}, ${bindIfParam(encrypted, left)})`\n return operator === 'notIlike' ? sql`NOT (${sqlFn})` : sqlFn\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.freeTextSearch,\n ) as Promise<SQL>\n}\n\n/**\n * Creates a JSONB operator that encrypts a JSON path selector and wraps it\n * in the appropriate `eql_v2` function call.\n *\n * Supports `jsonbPathQueryFirst`, `jsonbGet`, and `jsonbPathExists`.\n * The column must have `searchableJson` enabled in its {@link EncryptedColumnConfig}.\n */\nfunction createJsonbOperator(\n operator: 'jsonbPathQueryFirst' | 'jsonbGet' | 'jsonbPathExists',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: ProtectTable<ProtectTableColumn> | undefined,\n tableCache: Map<string, ProtectTable<ProtectTableColumn>>,\n): Promise<SQL> {\n const { config } = columnInfo\n const encryptedSelector = (value: unknown) =>\n sql`${bindIfParam(value, left)}::eql_v2_encrypted`\n\n if (!config?.searchableJson) {\n throw new EncryptionOperatorError(\n `The ${operator} operator requires searchableJson to be enabled on the column configuration.`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n switch (operator) {\n case 'jsonbPathQueryFirst':\n return sql`eql_v2.jsonb_path_query_first(${left}, ${encryptedSelector(encrypted)})`\n case 'jsonbGet':\n return sql`${left} -> ${encryptedSelector(encrypted)}`\n case 'jsonbPathExists':\n return sql`eql_v2.jsonb_path_exists(${left}, ${encryptedSelector(encrypted)})`\n }\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined,\n undefined,\n queryTypes.steVecSelector,\n ) as Promise<SQL>\n}\n\n// ============================================================================\n// Public API: createEncryptionOperators\n// ============================================================================\n\n/**\n * Creates a set of encryption-aware operators that automatically encrypt values\n * for encrypted columns before using them with Drizzle operators.\n *\n * For equality and text search operators (eq, ne, like, ilike, inArray, etc.):\n * Values are encrypted and then passed to regular Drizzle operators, which use\n * PostgreSQL's built-in operators for eql_v2_encrypted types.\n *\n * For order and range operators (gt, gte, lt, lte, between, notBetween):\n * Values are encrypted and then use eql_v2.* functions (eql_v2.gt(), eql_v2.gte(), etc.)\n * which are required for ORE (Order-Revealing Encryption) comparisons.\n *\n * @param encryptionClient - The EncryptionClient instance\n * @returns An object with all Drizzle operators wrapped for encrypted columns\n *\n * @example\n * ```ts\n * // Initialize operators\n * const ops = createEncryptionOperators(encryptionClient)\n *\n * // Equality search - automatically encrypts and uses PostgreSQL operators\n * const results = await db\n * .select()\n * .from(usersTable)\n * .where(await ops.eq(usersTable.email, 'user@example.com'))\n *\n * // Range query - automatically encrypts and uses eql_v2.gte()\n * const olderUsers = await db\n * .select()\n * .from(usersTable)\n * .where(await ops.gte(usersTable.age, 25))\n * ```\n */\nexport function createEncryptionOperators(encryptionClient: EncryptionClient): {\n // Comparison operators\n /**\n * Equality operator - encrypts value for encrypted columns.\n * Requires either `equality` or `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users with a specific email address.\n * ```ts\n * const condition = await ops.eq(usersTable.email, 'user@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n eq: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Not equal operator - encrypts value for encrypted columns.\n * Requires either `equality` or `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users whose email address is not a specific value.\n * ```ts\n * const condition = await ops.ne(usersTable.email, 'user@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n ne: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Greater than operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users older than a specific age.\n * ```ts\n * const condition = await ops.gt(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n gt: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Greater than or equal operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users older than or equal to a specific age.\n * ```ts\n * const condition = await ops.gte(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n gte: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Less than operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users younger than a specific age.\n * ```ts\n * const condition = await ops.lt(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n lt: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Less than or equal operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users younger than or equal to a specific age.\n * ```ts\n * const condition = await ops.lte(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n lte: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Between operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users within a specific age range.\n * ```ts\n * const condition = await ops.between(usersTable.age, 20, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n between: (left: SQLWrapper, min: unknown, max: unknown) => Promise<SQL> | SQL\n\n /**\n * Not between operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users outside a specific age range.\n * ```ts\n * const condition = await ops.notBetween(usersTable.age, 20, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n notBetween: (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ) => Promise<SQL> | SQL\n\n /**\n * Like operator for encrypted columns with free text search.\n * Requires `freeTextSearch` to be set on {@link EncryptedColumnConfig}.\n *\n * > [!IMPORTANT]\n * > Case sensitivity on encrypted columns depends on the {@link EncryptedColumnConfig}.\n * > Ensure that the column is configured for case-insensitive search if needed.\n *\n * @example\n * Select users with email addresses matching a pattern.\n * ```ts\n * const condition = await ops.like(usersTable.email, '%@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n like: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * ILike operator for encrypted columns with free text search.\n * Requires `freeTextSearch` to be set on {@link EncryptedColumnConfig}.\n *\n * > [!IMPORTANT]\n * > Case sensitivity on encrypted columns depends on the {@link EncryptedColumnConfig}.\n * > Ensure that the column is configured for case-insensitive search if needed.\n *\n * @example\n * Select users with email addresses matching a pattern (case-insensitive).\n * ```ts\n * const condition = await ops.ilike(usersTable.email, '%@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n ilike: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n notIlike: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * JSONB path query first operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and calls `eql_v2.jsonb_path_query_first()`,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbPathQueryFirst: (left: SQLWrapper, right: unknown) => Promise<SQL>\n\n /**\n * JSONB get operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and uses the `->` operator,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbGet: (left: SQLWrapper, right: unknown) => Promise<SQL>\n\n /**\n * JSONB path exists operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and calls `eql_v2.jsonb_path_exists()`,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbPathExists: (left: SQLWrapper, right: unknown) => Promise<SQL>\n // Array operators\n inArray: (left: SQLWrapper, right: unknown[] | SQLWrapper) => Promise<SQL>\n notInArray: (left: SQLWrapper, right: unknown[] | SQLWrapper) => Promise<SQL>\n // Sorting operators\n asc: (column: SQLWrapper) => SQL\n desc: (column: SQLWrapper) => SQL\n and: (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ) => Promise<SQL>\n or: (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ) => Promise<SQL>\n // Operators that don't need encryption (pass through to Drizzle)\n exists: typeof exists\n notExists: typeof notExists\n isNull: typeof isNull\n isNotNull: typeof isNotNull\n not: typeof not\n // Array operators that work with arrays directly (not encrypted values)\n arrayContains: typeof arrayContains\n arrayContained: typeof arrayContained\n arrayOverlaps: typeof arrayOverlaps\n} {\n // Create a cache for encrypted tables keyed by table name\n const tableCache = new Map<string, ProtectTable<ProtectTableColumn>>()\n const defaultTable: ProtectTable<ProtectTableColumn> | undefined = undefined\n\n /**\n * Equality operator - encrypts value and uses regular Drizzle operator\n */\n const encryptedEq = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'eq',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not equal operator - encrypts value and uses regular Drizzle operator\n */\n const encryptedNe = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'ne',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Greater than operator - uses eql_v2.gt() for encrypted columns with ORE index\n */\n const encryptedGt = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'gt',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Greater than or equal operator - uses eql_v2.gte() for encrypted columns with ORE index\n */\n const encryptedGte = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'gte',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Less than operator - uses eql_v2.lt() for encrypted columns with ORE index\n */\n const encryptedLt = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'lt',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Less than or equal operator - uses eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedLte = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'lte',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Between operator - uses eql_v2.gte() and eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedBetween = (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createRangeOperator(\n 'between',\n left,\n min,\n max,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not between operator - uses eql_v2.gte() and eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedNotBetween = (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createRangeOperator(\n 'notBetween',\n left,\n min,\n max,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Like operator - encrypts value and uses eql_v2.like() for encrypted columns with match index\n */\n const encryptedLike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'like',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Case-insensitive like operator - encrypts value and uses eql_v2.ilike() for encrypted columns with match index\n */\n const encryptedIlike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'ilike',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not like operator (case insensitive) - encrypts value and uses eql_v2.ilike() for encrypted columns with match index\n */\n const encryptedNotIlike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'notIlike',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB path query first operator - encrypts the selector and calls\n * `eql_v2.jsonb_path_query_first()` for encrypted columns with searchable JSON.\n */\n const encryptedJsonbPathQueryFirst = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbPathQueryFirst',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB get operator - encrypts the selector and uses the `->` operator\n * for encrypted columns with searchable JSON.\n */\n const encryptedJsonbGet = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbGet',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB path exists operator - encrypts the selector and calls\n * `eql_v2.jsonb_path_exists()` for encrypted columns with searchable JSON.\n */\n const encryptedJsonbPathExists = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbPathExists',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * In array operator - encrypts all values in the array\n */\n const encryptedInArray = async (\n left: SQLWrapper,\n right: unknown[] | SQLWrapper,\n ): Promise<SQL> => {\n // If right is a SQLWrapper (subquery), pass through to Drizzle\n if (isSQLWrapper(right)) {\n return inArray(left, right as unknown as Parameters<typeof inArray>[1])\n }\n\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n\n if (!columnInfo.config?.equality || !Array.isArray(right)) {\n return inArray(left, right as unknown[])\n }\n\n // Encrypt all values in the array in a single batch\n const encryptedValues = await encryptValues(\n encryptionClient,\n right.map((value) => ({\n value,\n column: left,\n queryType: queryTypes.equality,\n })),\n defaultTable,\n tableCache,\n )\n\n // Use regular eq for each encrypted value - PostgreSQL operators handle it\n const conditions = encryptedValues\n .filter((encrypted) => encrypted !== undefined)\n .map((encrypted) => eq(left, encrypted))\n\n if (conditions.length === 0) {\n return sql`false`\n }\n\n const combined = or(...conditions)\n return combined ?? sql`false`\n }\n\n /**\n * Not in array operator\n */\n const encryptedNotInArray = async (\n left: SQLWrapper,\n right: unknown[] | SQLWrapper,\n ): Promise<SQL> => {\n // If right is a SQLWrapper (subquery), pass through to Drizzle\n if (isSQLWrapper(right)) {\n return notInArray(\n left,\n right as unknown as Parameters<typeof notInArray>[1],\n )\n }\n\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n\n if (!columnInfo.config?.equality || !Array.isArray(right)) {\n return notInArray(left, right as unknown[])\n }\n\n // Encrypt all values in the array in a single batch\n const encryptedValues = await encryptValues(\n encryptionClient,\n right.map((value) => ({\n value,\n column: left,\n queryType: queryTypes.equality,\n })),\n defaultTable,\n tableCache,\n )\n\n // Use regular ne for each encrypted value - PostgreSQL operators handle it\n const conditions = encryptedValues\n .filter((encrypted) => encrypted !== undefined)\n .map((encrypted) => ne(left, encrypted))\n\n if (conditions.length === 0) {\n return sql`true`\n }\n\n const combined = and(...conditions)\n return combined ?? sql`true`\n }\n\n /**\n * Ascending order helper - uses eql_v2.order_by() for encrypted columns with ORE index\n */\n const encryptedAsc = (column: SQLWrapper): SQL => {\n const columnInfo = getColumnInfo(column, defaultTable, tableCache)\n\n if (columnInfo.config?.orderAndRange) {\n return asc(sql`eql_v2.order_by(${column})`)\n }\n\n return asc(column)\n }\n\n /**\n * Descending order helper - uses eql_v2.order_by() for encrypted columns with ORE index\n */\n const encryptedDesc = (column: SQLWrapper): SQL => {\n const columnInfo = getColumnInfo(column, defaultTable, tableCache)\n\n if (columnInfo.config?.orderAndRange) {\n return desc(sql`eql_v2.order_by(${column})`)\n }\n\n return desc(column)\n }\n\n /**\n * Batched AND operator - collects lazy operators, batches encryption, and combines conditions\n */\n const encryptedAnd = async (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ): Promise<SQL> => {\n // Single pass: separate lazy operators from regular conditions\n const lazyOperators: LazyOperator[] = []\n const regularConditions: (SQL | SQLWrapper | undefined)[] = []\n const regularPromises: Promise<SQL>[] = []\n\n for (const condition of conditions) {\n if (condition === undefined) {\n continue\n }\n\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else if (condition instanceof Promise) {\n // Check if promise is also a lazy operator\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else {\n regularPromises.push(condition)\n }\n } else {\n regularConditions.push(condition)\n }\n }\n\n // If there are no lazy operators, just use Drizzle's and()\n if (lazyOperators.length === 0) {\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...(await Promise.all(regularPromises)),\n ]\n return and(...allConditions) ?? sql`true`\n }\n\n // Single pass: collect all values to encrypt with metadata\n const valuesToEncrypt: Array<{\n value: unknown\n column: SQLWrapper\n columnInfo: ColumnInfo\n queryType?: QueryTypeName\n lazyOpIndex: number\n isMin?: boolean\n isMax?: boolean\n }> = []\n\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n if (!lazyOp.needsEncryption) {\n continue\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.min,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMin: true,\n })\n valuesToEncrypt.push({\n value: lazyOp.max,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMax: true,\n })\n } else if (lazyOp.right !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.right,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n })\n }\n }\n\n // Batch encrypt all values\n const encryptedResults = await encryptValues(\n encryptionClient,\n valuesToEncrypt.map((v) => ({\n value: v.value,\n column: v.column,\n queryType: v.queryType,\n })),\n defaultTable,\n tableCache,\n )\n\n // Group encrypted values by lazy operator index\n const encryptedByLazyOp = new Map<\n number,\n { value?: unknown; min?: unknown; max?: unknown }\n >()\n\n for (let i = 0; i < valuesToEncrypt.length; i++) {\n const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i]\n const encrypted = encryptedResults[i]\n\n let group = encryptedByLazyOp.get(lazyOpIndex)\n if (!group) {\n group = {}\n encryptedByLazyOp.set(lazyOpIndex, group)\n }\n\n if (isMin) {\n group.min = encrypted\n } else if (isMax) {\n group.max = encrypted\n } else {\n group.value = encrypted\n }\n }\n\n // Execute all lazy operators with their encrypted values\n const sqlConditions: SQL[] = []\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n const encrypted = encryptedByLazyOp.get(i)\n\n let sqlCondition: SQL\n if (lazyOp.needsEncryption && encrypted) {\n const encryptedValues: Array<{ value: unknown; encrypted: unknown }> =\n []\n if (encrypted.value !== undefined) {\n encryptedValues.push({\n value: lazyOp.right,\n encrypted: encrypted.value,\n })\n }\n if (encrypted.min !== undefined) {\n encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min })\n }\n if (encrypted.max !== undefined) {\n encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max })\n }\n sqlCondition = await executeLazyOperator(lazyOp, encryptedValues)\n } else {\n sqlCondition = lazyOp.execute(lazyOp.right)\n }\n\n sqlConditions.push(sqlCondition)\n }\n\n // Await any regular promises\n const regularPromisesResults = await Promise.all(regularPromises)\n\n // Combine all conditions\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...sqlConditions,\n ...regularPromisesResults,\n ]\n\n return and(...allConditions) ?? sql`true`\n }\n\n /**\n * Batched OR operator - collects lazy operators, batches encryption, and combines conditions\n */\n const encryptedOr = async (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ): Promise<SQL> => {\n const lazyOperators: LazyOperator[] = []\n const regularConditions: (SQL | SQLWrapper | undefined)[] = []\n const regularPromises: Promise<SQL>[] = []\n\n for (const condition of conditions) {\n if (condition === undefined) {\n continue\n }\n\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else if (condition instanceof Promise) {\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else {\n regularPromises.push(condition)\n }\n } else {\n regularConditions.push(condition)\n }\n }\n\n if (lazyOperators.length === 0) {\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...(await Promise.all(regularPromises)),\n ]\n return or(...allConditions) ?? sql`false`\n }\n\n const valuesToEncrypt: Array<{\n value: unknown\n column: SQLWrapper\n columnInfo: ColumnInfo\n queryType?: QueryTypeName\n lazyOpIndex: number\n isMin?: boolean\n isMax?: boolean\n }> = []\n\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n if (!lazyOp.needsEncryption) {\n continue\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.min,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMin: true,\n })\n valuesToEncrypt.push({\n value: lazyOp.max,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMax: true,\n })\n } else if (lazyOp.right !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.right,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n })\n }\n }\n\n const encryptedResults = await encryptValues(\n encryptionClient,\n valuesToEncrypt.map((v) => ({\n value: v.value,\n column: v.column,\n queryType: v.queryType,\n })),\n defaultTable,\n tableCache,\n )\n\n const encryptedByLazyOp = new Map<\n number,\n { value?: unknown; min?: unknown; max?: unknown }\n >()\n\n for (let i = 0; i < valuesToEncrypt.length; i++) {\n const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i]\n const encrypted = encryptedResults[i]\n\n let group = encryptedByLazyOp.get(lazyOpIndex)\n if (!group) {\n group = {}\n encryptedByLazyOp.set(lazyOpIndex, group)\n }\n\n if (isMin) {\n group.min = encrypted\n } else if (isMax) {\n group.max = encrypted\n } else {\n group.value = encrypted\n }\n }\n\n const sqlConditions: SQL[] = []\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n const encrypted = encryptedByLazyOp.get(i)\n\n let sqlCondition: SQL\n if (lazyOp.needsEncryption && encrypted) {\n const encryptedValues: Array<{ value: unknown; encrypted: unknown }> =\n []\n if (encrypted.value !== undefined) {\n encryptedValues.push({\n value: lazyOp.right,\n encrypted: encrypted.value,\n })\n }\n if (encrypted.min !== undefined) {\n encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min })\n }\n if (encrypted.max !== undefined) {\n encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max })\n }\n sqlCondition = await executeLazyOperator(lazyOp, encryptedValues)\n } else {\n sqlCondition = lazyOp.execute(lazyOp.right)\n }\n\n sqlConditions.push(sqlCondition)\n }\n\n const regularPromisesResults = await Promise.all(regularPromises)\n\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...sqlConditions,\n ...regularPromisesResults,\n ]\n\n return or(...allConditions) ?? sql`false`\n }\n\n return {\n // Comparison operators\n eq: encryptedEq,\n ne: encryptedNe,\n gt: encryptedGt,\n gte: encryptedGte,\n lt: encryptedLt,\n lte: encryptedLte,\n\n // Range operators\n between: encryptedBetween,\n notBetween: encryptedNotBetween,\n\n // Text search operators\n like: encryptedLike,\n ilike: encryptedIlike,\n notIlike: encryptedNotIlike,\n\n // Searchable JSON operators\n jsonbPathQueryFirst: encryptedJsonbPathQueryFirst,\n jsonbGet: encryptedJsonbGet,\n jsonbPathExists: encryptedJsonbPathExists,\n\n // Array operators\n inArray: encryptedInArray,\n notInArray: encryptedNotInArray,\n\n // Sorting operators\n asc: encryptedAsc,\n desc: encryptedDesc,\n\n // AND operator - batches encryption operations\n and: encryptedAnd,\n\n // OR operator - batches encryption operations\n or: encryptedOr,\n\n // Operators that don't need encryption (pass through to Drizzle)\n exists,\n notExists,\n isNull,\n isNotNull,\n not,\n // Array operators that work with arrays directly (not encrypted values)\n arrayContains,\n arrayContained,\n arrayOverlaps,\n }\n}\n"],"mappings":"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","names":["encryptedTable","config","encryptedColumn","sql","allConditions"]}
1
+ {"version":3,"sources":["../../src/drizzle/index.ts","../../src/drizzle/schema-extraction.ts","../../src/drizzle/operators.ts"],"sourcesContent":["import type { CastAs, MatchIndexOpts, TokenFilter } from '@/schema'\nimport { customType } from 'drizzle-orm/pg-core'\n\nexport type { CastAs, MatchIndexOpts, TokenFilter }\n\n/**\n * Configuration for encrypted column indexes and data types\n */\nexport type EncryptedColumnConfig = {\n /**\n * Data type for the column (default: 'string')\n */\n dataType?: CastAs\n /**\n * Enable free text search. Can be a boolean for default options, or an object for custom configuration.\n */\n freeTextSearch?: boolean | MatchIndexOpts\n /**\n * Enable equality index. Can be a boolean for default options, or an array of token filters.\n */\n equality?: boolean | TokenFilter[]\n /**\n * Enable order and range index for sorting and range queries.\n */\n orderAndRange?: boolean\n /**\n * Enable searchable JSON index for JSONB path queries.\n * Requires dataType: 'json'.\n */\n searchableJson?: boolean\n}\n\n/**\n * Map to store configuration for encrypted columns\n * Keyed by column name (the name passed to encryptedType)\n */\nconst columnConfigMap = new Map<\n string,\n EncryptedColumnConfig & { name: string }\n>()\n\n/**\n * Creates an encrypted column type for Drizzle ORM with configurable searchable encryption options.\n *\n * When data is encrypted, the actual stored value is an [EQL v2](/docs/reference/eql) encrypted composite type which includes any searchable encryption indexes defined for the column.\n * Importantly, the original data type is not known until it is decrypted. Therefore, this function allows specifying\n * the original data type via the `dataType` option in the configuration.\n * This ensures that when data is decrypted, it can be correctly interpreted as the intended TypeScript type.\n *\n * @typeParam TData - The TypeScript type of the data stored in the column\n * @param name - The column name in the database\n * @param config - Optional configuration for data type and searchable encryption indexes\n * @returns A Drizzle column type that can be used in pgTable definitions\n *\n * ## Searchable Encryption Options\n *\n * - `dataType`: Specifies the original data type of the column (e.g., 'string', 'number', 'json'). Default is 'string'.\n * - `freeTextSearch`: Enables free text search index. Can be a boolean for default options, or an object for custom configuration.\n * - `equality`: Enables equality index. Can be a boolean for default options, or an array of token filters.\n * - `orderAndRange`: Enables order and range index for sorting and range queries.\n * - `searchableJson`: Enables searchable JSON index for JSONB path queries on encrypted JSON columns.\n *\n * See {@link EncryptedColumnConfig}.\n *\n * @example\n * Defining a drizzle table schema for postgres table with encrypted columns.\n *\n * ```typescript\n * import { pgTable, integer, timestamp } from 'drizzle-orm/pg-core'\n * import { encryptedType } from '@cipherstash/stack/drizzle'\n *\n * const users = pgTable('users', {\n * email: encryptedType('email', {\n * freeTextSearch: true,\n * equality: true,\n * orderAndRange: true,\n * }),\n * age: encryptedType('age', {\n * dataType: 'number',\n * equality: true,\n * orderAndRange: true,\n * }),\n * profile: encryptedType('profile', {\n * dataType: 'json',\n * }),\n * })\n * ```\n */\nexport const encryptedType = <TData>(\n name: string,\n config?: EncryptedColumnConfig,\n) => {\n // Create the Drizzle custom type\n const customColumnType = customType<{ data: TData; driverData: string }>({\n dataType() {\n return 'eql_v2_encrypted'\n },\n toDriver(value: TData): string {\n const jsonStr = JSON.stringify(value)\n const escaped = jsonStr.replace(/\"/g, '\"\"')\n return `(\"${escaped}\")`\n },\n fromDriver(value: string): TData {\n const parseComposite = (str: string) => {\n if (!str || str === '') return null\n\n const trimmed = str.trim()\n\n if (trimmed.startsWith('(') && trimmed.endsWith(')')) {\n let inner = trimmed.slice(1, -1)\n inner = inner.replace(/\"\"/g, '\"')\n\n if (inner.startsWith('\"') && inner.endsWith('\"')) {\n const stripped = inner.slice(1, -1)\n return JSON.parse(stripped)\n }\n\n if (inner.startsWith('{') || inner.startsWith('[')) {\n return JSON.parse(inner)\n }\n\n return inner\n }\n\n return JSON.parse(str)\n }\n\n return parseComposite(value) as TData\n },\n })\n\n // Create the column instance\n const column = customColumnType(name)\n\n // Store configuration keyed by column name\n // This allows us to look it up during schema extraction\n const fullConfig: EncryptedColumnConfig & { name: string } = {\n name,\n ...config,\n }\n\n // Store in Map keyed by column name (will be looked up during extraction)\n columnConfigMap.set(name, fullConfig)\n\n // Also store on property for immediate access (before pgTable processes it)\n // We need to use any here because Drizzle columns don't have a type for custom properties\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle columns don't expose custom property types\n ;(column as any)._encryptionConfig = fullConfig\n\n return column\n}\n\n/**\n * Get configuration for an encrypted column by checking if it's an encrypted type\n * and looking up the config by column name\n * @internal\n */\nexport function getEncryptedColumnConfig(\n columnName: string,\n column: unknown,\n): (EncryptedColumnConfig & { name: string }) | undefined {\n // Check if this is an encrypted column\n if (column && typeof column === 'object') {\n // We need to use any here to access Drizzle column properties\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle column types don't expose all properties\n const columnAny = column as any\n\n // Check if it's an encrypted column by checking sqlName or dataType\n // After pgTable processes it, sqlName will be 'eql_v2_encrypted'\n const isEncrypted =\n columnAny.sqlName === 'eql_v2_encrypted' ||\n columnAny.dataType === 'eql_v2_encrypted' ||\n (columnAny.dataType &&\n typeof columnAny.dataType === 'function' &&\n columnAny.dataType() === 'eql_v2_encrypted')\n\n if (isEncrypted) {\n // Try to get config from property (if still there)\n if (columnAny._encryptionConfig) {\n return columnAny._encryptionConfig\n }\n\n // Look up config by column name (the name passed to encryptedType)\n // The column.name should match what was passed to encryptedType\n const lookupName = columnAny.name || columnName\n return columnConfigMap.get(lookupName)\n }\n }\n return undefined\n}\n\n/**\n * Extract a CipherStash encryption schema from a Drizzle table definition.\n *\n * Inspects columns created with {@link encryptedType} and builds the equivalent\n * `encryptedTable` / `encryptedColumn` schema automatically.\n */\nexport { extractEncryptionSchema } from './schema-extraction.js'\n\n/**\n * Create Drizzle query operators (`eq`, `lt`, `gt`, etc.) that work with\n * encrypted columns. The returned operators encrypt query values before\n * passing them to Drizzle, enabling searchable encryption in standard\n * Drizzle queries.\n */\nexport {\n createEncryptionOperators,\n EncryptionOperatorError,\n EncryptionConfigError,\n} from './operators.js'\n","import { type EncryptedColumn, encryptedColumn, encryptedTable } from '@/schema'\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport { getEncryptedColumnConfig } from './index.js'\n\n/**\n * Extracts an encryption schema from a Drizzle table definition.\n * This function identifies columns created with `encryptedType` and\n * builds a corresponding `EncryptedTable` with `encryptedColumn` definitions.\n *\n * @param table - The Drizzle table definition\n * @returns A EncryptedTable that can be used with encryption client initialization\n *\n * @example\n * ```ts\n * const drizzleUsersTable = pgTable('users', {\n * email: encryptedType('email', { freeTextSearch: true, equality: true }),\n * age: encryptedType('age', { dataType: 'number', orderAndRange: true }),\n * })\n *\n * const encryptionSchema = extractEncryptionSchema(drizzleUsersTable)\n * const client = await createEncryptionClient({ schemas: [encryptionSchema.build()] })\n * ```\n */\n// We use any for the PgTable generic because we need to access Drizzle's internal properties\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle table types don't expose Symbol properties\nexport function extractEncryptionSchema<T extends PgTable<any>>(\n table: T,\n): ReturnType<typeof encryptedTable<Record<string, EncryptedColumn>>> {\n // Drizzle tables store the name in a Symbol property\n // biome-ignore lint/suspicious/noExplicitAny: Drizzle tables don't expose Symbol properties in types\n const tableName = (table as any)[Symbol.for('drizzle:Name')] as\n | string\n | undefined\n if (!tableName) {\n throw new Error(\n 'Unable to extract table name from Drizzle table. Ensure you are using a table created with pgTable().',\n )\n }\n\n const columns: Record<string, EncryptedColumn> = {}\n\n // Iterate through table columns\n for (const [columnName, column] of Object.entries(table)) {\n // Skip if it's not a column (could be methods or other properties)\n if (typeof column !== 'object' || column === null) {\n continue\n }\n\n // Check if this column has encrypted configuration\n const config = getEncryptedColumnConfig(columnName, column)\n\n if (config) {\n // Extract the actual column name from the column object (not the schema key)\n // Drizzle columns have a 'name' property that contains the actual database column name\n const actualColumnName = column.name || config.name\n\n // This is an encrypted column - build encryptedColumn using the actual column name\n const csCol = encryptedColumn(actualColumnName)\n\n // Apply data type\n if (config.dataType && config.dataType !== 'string') {\n csCol.dataType(config.dataType)\n }\n\n // Apply indexes based on configuration\n if (config.orderAndRange) {\n csCol.orderAndRange()\n }\n\n if (config.equality) {\n if (Array.isArray(config.equality)) {\n // Custom token filters\n csCol.equality(config.equality)\n } else {\n // Default equality (boolean true)\n csCol.equality()\n }\n }\n\n if (config.freeTextSearch) {\n if (typeof config.freeTextSearch === 'object') {\n // Custom match options\n csCol.freeTextSearch(config.freeTextSearch)\n } else {\n // Default freeTextSearch (boolean true)\n csCol.freeTextSearch()\n }\n }\n\n if (config.searchableJson) {\n if (config.dataType !== 'json') {\n throw new Error(\n `Column \"${columnName}\" has searchableJson enabled but dataType is \"${config.dataType ?? 'string'}\". searchableJson requires dataType: 'json'.`,\n )\n }\n csCol.searchableJson()\n }\n\n columns[actualColumnName] = csCol\n }\n }\n\n if (Object.keys(columns).length === 0) {\n throw new Error(\n `No encrypted columns found in table \"${tableName}\". Use encryptedType() to define encrypted columns.`,\n )\n }\n\n return encryptedTable(tableName, columns)\n}\n","import type { EncryptionClient } from '@/encryption/index.js'\nimport type {\n EncryptedColumn,\n EncryptedTable,\n EncryptedTableColumn,\n} from '@/schema'\nimport { type QueryTypeName, queryTypes } from '@/types'\nimport {\n type SQL,\n type SQLWrapper,\n and,\n arrayContained,\n arrayContains,\n arrayOverlaps,\n asc,\n between,\n desc,\n eq,\n exists,\n gt,\n gte,\n ilike,\n inArray,\n isNotNull,\n isNull,\n like,\n lt,\n lte,\n ne,\n not,\n notBetween,\n notExists,\n notIlike,\n notInArray,\n or,\n} from 'drizzle-orm'\nimport { bindIfParam, sql } from 'drizzle-orm'\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport type { EncryptedColumnConfig } from './index.js'\nimport { getEncryptedColumnConfig } from './index.js'\nimport { extractEncryptionSchema } from './schema-extraction.js'\n\n// ============================================================================\n// Type Definitions and Type Guards\n// ============================================================================\n\n/**\n * Branded type for Drizzle table with encrypted columns\n */\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle table types don't expose Symbol properties\ntype EncryptedDrizzleTable = PgTable<any> & {\n readonly __isEncryptedTable?: true\n}\n\n/**\n * Type guard to check if a value is a Drizzle SQLWrapper\n */\nfunction isSQLWrapper(value: unknown): value is SQLWrapper {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'sql' in value &&\n typeof (value as { sql: unknown }).sql !== 'undefined'\n )\n}\n\n/**\n * Type guard to check if a value is a Drizzle table\n */\nfunction isPgTable(value: unknown): value is EncryptedDrizzleTable {\n return (\n typeof value === 'object' &&\n value !== null &&\n Symbol.for('drizzle:Name') in value\n )\n}\n\n/**\n * Custom error types for better debugging\n */\nexport class EncryptionOperatorError extends Error {\n constructor(\n message: string,\n public readonly context?: {\n tableName?: string\n columnName?: string\n operator?: string\n },\n ) {\n super(message)\n this.name = 'EncryptionOperatorError'\n }\n}\n\nexport class EncryptionConfigError extends EncryptionOperatorError {\n constructor(message: string, context?: EncryptionOperatorError['context']) {\n super(message, context)\n this.name = 'EncryptionConfigError'\n }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Helper to extract table name from a Drizzle table\n */\nfunction getDrizzleTableName(drizzleTable: unknown): string | undefined {\n if (!isPgTable(drizzleTable)) {\n return undefined\n }\n // Access Symbol property using Record type to avoid indexing errors\n const tableWithSymbol = drizzleTable as unknown as Record<\n symbol,\n string | undefined\n >\n return tableWithSymbol[Symbol.for('drizzle:Name')]\n}\n\n/**\n * Helper to get the drizzle table from a drizzle column\n */\nfunction getDrizzleTableFromColumn(drizzleColumn: SQLWrapper): unknown {\n const column = drizzleColumn as unknown as Record<string, unknown>\n return column.table as unknown\n}\n\n/**\n * Helper to extract encrypted table from a drizzle column by deriving it from the column's parent table\n */\nfunction getEncryptedTableFromColumn(\n drizzleColumn: SQLWrapper,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): EncryptedTable<EncryptedTableColumn> | undefined {\n const drizzleTable = getDrizzleTableFromColumn(drizzleColumn)\n if (!drizzleTable) {\n return undefined\n }\n\n const tableName = getDrizzleTableName(drizzleTable)\n if (!tableName) {\n return undefined\n }\n\n // Check cache first\n let encryptedTable = tableCache.get(tableName)\n if (encryptedTable) {\n return encryptedTable\n }\n\n // Extract encryption schema from drizzle table and cache it\n try {\n // biome-ignore lint/suspicious/noExplicitAny: PgTable type doesn't expose all needed properties\n encryptedTable = extractEncryptionSchema(drizzleTable as PgTable<any>)\n tableCache.set(tableName, encryptedTable)\n return encryptedTable\n } catch {\n // Table doesn't have encrypted columns or extraction failed\n return undefined\n }\n}\n\n/**\n * Helper to get the encrypted column definition for a Drizzle column from the encrypted table\n */\nfunction getEncryptedColumn(\n drizzleColumn: SQLWrapper,\n encryptedTable: EncryptedTable<EncryptedTableColumn>,\n): EncryptedColumn | undefined {\n const column = drizzleColumn as unknown as Record<string, unknown>\n const columnName = column.name as string | undefined\n if (!columnName) {\n return undefined\n }\n\n const tableRecord = encryptedTable as unknown as Record<string, unknown>\n return tableRecord[columnName] as EncryptedColumn | undefined\n}\n\n/**\n * Column metadata extracted from a Drizzle column\n */\ninterface ColumnInfo {\n readonly encryptedColumn: EncryptedColumn | undefined\n readonly config: (EncryptedColumnConfig & { name: string }) | undefined\n readonly encryptedTable: EncryptedTable<EncryptedTableColumn> | undefined\n readonly columnName: string\n readonly tableName: string | undefined\n}\n\n/**\n * Helper to get the encrypted column and column config for a Drizzle column\n * If encryptedTable is not provided, it will be derived from the column\n */\nfunction getColumnInfo(\n drizzleColumn: SQLWrapper,\n encryptedTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): ColumnInfo {\n const column = drizzleColumn as unknown as Record<string, unknown>\n const columnName = (column.name as string | undefined) || 'unknown'\n\n // If encryptedTable not provided, try to derive it from the column\n let resolvedTable = encryptedTable\n if (!resolvedTable) {\n resolvedTable = getEncryptedTableFromColumn(drizzleColumn, tableCache)\n }\n\n const drizzleTable = getDrizzleTableFromColumn(drizzleColumn)\n const tableName = getDrizzleTableName(drizzleTable)\n\n if (!resolvedTable) {\n // Column is not from an encrypted table\n const config = getEncryptedColumnConfig(columnName, drizzleColumn)\n return {\n encryptedColumn: undefined,\n config,\n encryptedTable: undefined,\n columnName,\n tableName,\n }\n }\n\n const encryptedColumn = getEncryptedColumn(drizzleColumn, resolvedTable)\n const config = getEncryptedColumnConfig(columnName, drizzleColumn)\n\n return {\n encryptedColumn,\n config,\n encryptedTable: resolvedTable,\n columnName,\n tableName,\n }\n}\n\n/**\n * Helper to convert a value to plaintext format\n */\nfunction toPlaintext(value: unknown): string | number {\n if (typeof value === 'boolean') {\n return value ? 1 : 0\n }\n if (typeof value === 'string' || typeof value === 'number') {\n return value\n }\n if (value instanceof Date) {\n return value.toISOString()\n }\n return String(value)\n}\n\n/**\n * Value to encrypt with its associated column\n */\ninterface ValueToEncrypt {\n readonly value: string | number\n readonly column: SQLWrapper\n readonly columnInfo: ColumnInfo\n readonly queryType?: QueryTypeName\n readonly originalIndex: number\n}\n\n/**\n * Helper to encrypt multiple values for use in a query\n * Returns an array of encrypted search terms or original values if not encrypted\n */\nasync function encryptValues(\n encryptionClient: EncryptionClient,\n values: Array<{\n value: unknown\n column: SQLWrapper\n queryType?: QueryTypeName\n }>,\n encryptedTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<unknown[]> {\n if (values.length === 0) {\n return []\n }\n\n // Single pass: collect values to encrypt with their metadata\n const valuesToEncrypt: ValueToEncrypt[] = []\n const results: unknown[] = new Array(values.length)\n\n for (let i = 0; i < values.length; i++) {\n const { value, column, queryType } = values[i]\n const columnInfo = getColumnInfo(column, encryptedTable, tableCache)\n\n if (\n !columnInfo.encryptedColumn ||\n !columnInfo.config ||\n !columnInfo.encryptedTable\n ) {\n // Column is not encrypted, return value as-is\n results[i] = value\n continue\n }\n\n const plaintextValue = toPlaintext(value)\n valuesToEncrypt.push({\n value: plaintextValue,\n column,\n columnInfo,\n queryType,\n originalIndex: i,\n })\n }\n\n if (valuesToEncrypt.length === 0) {\n return results\n }\n\n // Group values by column to batch encrypt with same column/table\n const columnGroups = new Map<\n string,\n {\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n columnName: string\n values: Array<{\n value: string | number\n index: number\n queryType?: QueryTypeName\n }>\n resultIndices: number[]\n }\n >()\n\n let valueIndex = 0\n for (const {\n value,\n columnInfo,\n queryType,\n originalIndex,\n } of valuesToEncrypt) {\n // Safe access with validation - we know these exist from earlier checks\n if (\n !columnInfo.config ||\n !columnInfo.encryptedColumn ||\n !columnInfo.encryptedTable\n ) {\n continue\n }\n\n const columnName = columnInfo.config.name\n const groupKey = `${columnInfo.tableName ?? 'unknown'}/${columnName}`\n let group = columnGroups.get(groupKey)\n if (!group) {\n group = {\n column: columnInfo.encryptedColumn,\n table: columnInfo.encryptedTable,\n columnName,\n values: [],\n resultIndices: [],\n }\n columnGroups.set(groupKey, group)\n }\n group.values.push({ value, index: valueIndex++, queryType })\n group.resultIndices.push(originalIndex)\n }\n\n // Encrypt all values for each column in batches\n for (const [, group] of columnGroups) {\n const { columnName } = group\n try {\n const terms = group.values.map((v) => ({\n value: v.value,\n column: group.column,\n table: group.table,\n queryType: v.queryType,\n }))\n\n const encryptedTerms = await encryptionClient.encryptQuery(terms)\n\n if (encryptedTerms.failure) {\n throw new EncryptionOperatorError(\n `Failed to encrypt query terms for column \"${columnName}\": ${encryptedTerms.failure.message}`,\n { columnName },\n )\n }\n\n // Map results back to original indices\n for (let i = 0; i < group.values.length; i++) {\n const resultIndex = group.resultIndices[i] ?? -1\n if (resultIndex >= 0 && resultIndex < results.length) {\n results[resultIndex] = encryptedTerms.data[i]\n }\n }\n } catch (error) {\n if (error instanceof EncryptionOperatorError) {\n throw error\n }\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n throw new EncryptionOperatorError(\n `Unexpected error encrypting values for column \"${columnName}\": ${errorMessage}`,\n { columnName },\n )\n }\n }\n\n return results\n}\n\n/**\n * Helper to encrypt a single value for use in a query\n * Returns the encrypted search term or the original value if not encrypted\n */\nasync function encryptValue(\n encryptionClient: EncryptionClient,\n value: unknown,\n drizzleColumn: SQLWrapper,\n encryptedTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n queryType?: QueryTypeName,\n): Promise<unknown> {\n const results = await encryptValues(\n encryptionClient,\n [{ value, column: drizzleColumn, queryType }],\n encryptedTable,\n tableCache,\n )\n return results[0]\n}\n\n// ============================================================================\n// Lazy Operator Pattern\n// ============================================================================\n\n/**\n * Simplified lazy operator that defers encryption until awaited or batched\n */\ninterface LazyOperator {\n readonly __isLazyOperator: true\n readonly operator: string\n readonly queryType?: QueryTypeName\n readonly left: SQLWrapper\n readonly right: unknown\n readonly min?: unknown\n readonly max?: unknown\n readonly needsEncryption: boolean\n readonly columnInfo: ColumnInfo\n execute(\n encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ): SQL\n}\n\n/**\n * Type guard for lazy operators\n */\nfunction isLazyOperator(value: unknown): value is LazyOperator {\n return (\n typeof value === 'object' &&\n value !== null &&\n '__isLazyOperator' in value &&\n (value as LazyOperator).__isLazyOperator === true\n )\n}\n\n/**\n * Creates a lazy operator that defers execution\n */\nfunction createLazyOperator(\n operator: string,\n left: SQLWrapper,\n right: unknown,\n execute: (\n encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ) => SQL,\n needsEncryption: boolean,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n min?: unknown,\n max?: unknown,\n queryType?: QueryTypeName,\n): LazyOperator & Promise<SQL> {\n let resolvedSQL: SQL | undefined\n let encryptionPromise: Promise<SQL> | undefined\n\n const lazyOp: LazyOperator = {\n __isLazyOperator: true,\n operator,\n queryType,\n left,\n right,\n min,\n max,\n needsEncryption,\n columnInfo,\n execute,\n }\n\n // Create a promise that will be resolved when encryption completes\n const promise = new Promise<SQL>((resolve, reject) => {\n // Auto-execute when awaited directly\n queueMicrotask(async () => {\n if (resolvedSQL !== undefined) {\n resolve(resolvedSQL)\n return\n }\n\n try {\n if (!encryptionPromise) {\n encryptionPromise = executeLazyOperatorDirect(\n lazyOp,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n const sql = await encryptionPromise\n resolvedSQL = sql\n resolve(sql)\n } catch (error) {\n reject(error)\n }\n })\n })\n\n // Attach lazy operator properties to the promise\n return Object.assign(promise, lazyOp)\n}\n\n/**\n * Executes a lazy operator with pre-encrypted values (used in batched mode)\n */\nasync function executeLazyOperator(\n lazyOp: LazyOperator,\n encryptedValues?: { value: unknown; encrypted: unknown }[],\n): Promise<SQL> {\n if (!lazyOp.needsEncryption) {\n return lazyOp.execute(lazyOp.right)\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n // Between operator - use provided encrypted values\n let encryptedMin: unknown\n let encryptedMax: unknown\n\n if (encryptedValues && encryptedValues.length >= 2) {\n encryptedMin = encryptedValues[0]?.encrypted\n encryptedMax = encryptedValues[1]?.encrypted\n } else {\n throw new EncryptionOperatorError(\n 'Between operator requires both min and max encrypted values',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n if (encryptedMin === undefined || encryptedMax === undefined) {\n throw new EncryptionOperatorError(\n 'Between operator requires both min and max values to be encrypted',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n return lazyOp.execute(undefined, encryptedMin, encryptedMax)\n }\n\n // Single value operator\n let encrypted: unknown\n\n if (encryptedValues && encryptedValues.length > 0) {\n encrypted = encryptedValues[0]?.encrypted\n } else {\n throw new EncryptionOperatorError(\n 'Operator requires encrypted value but none provided',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n 'Encryption failed or value was not encrypted',\n {\n columnName: lazyOp.columnInfo.columnName,\n tableName: lazyOp.columnInfo.tableName,\n operator: lazyOp.operator,\n },\n )\n }\n\n return lazyOp.execute(encrypted)\n}\n\n/**\n * Executes a lazy operator directly by encrypting values on demand\n * Used when operator is awaited directly (not batched)\n */\nasync function executeLazyOperatorDirect(\n lazyOp: LazyOperator,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<SQL> {\n if (!lazyOp.needsEncryption) {\n return lazyOp.execute(lazyOp.right)\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n // Between operator - encrypt min and max\n const [encryptedMin, encryptedMax] = await encryptValues(\n encryptionClient,\n [\n { value: lazyOp.min, column: lazyOp.left, queryType: lazyOp.queryType },\n { value: lazyOp.max, column: lazyOp.left, queryType: lazyOp.queryType },\n ],\n defaultTable,\n tableCache,\n )\n return lazyOp.execute(undefined, encryptedMin, encryptedMax)\n }\n\n // Single value operator\n const encrypted = await encryptValue(\n encryptionClient,\n lazyOp.right,\n lazyOp.left,\n defaultTable,\n tableCache,\n lazyOp.queryType,\n )\n\n return lazyOp.execute(encrypted)\n}\n\n// ============================================================================\n// Operator Factory Functions\n// ============================================================================\n\n/**\n * Creates a comparison operator (eq, ne, gt, gte, lt, lte)\n */\nfunction createComparisonOperator(\n operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n // Operators requiring orderAndRange index\n const requiresOrderAndRange = ['gt', 'gte', 'lt', 'lte'].includes(operator)\n\n if (requiresOrderAndRange) {\n if (!config?.orderAndRange) {\n // Return regular Drizzle operator for non-encrypted columns\n switch (operator) {\n case 'gt':\n return gt(left, right)\n case 'gte':\n return gte(left, right)\n case 'lt':\n return lt(left, right)\n case 'lte':\n return lte(left, right)\n }\n }\n\n // This will be replaced with encrypted value in executeLazyOperator\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n return sql`eql_v2.${sql.raw(operator)}(${left}, ${bindIfParam(encrypted, left)})`\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.orderAndRange,\n ) as Promise<SQL>\n }\n\n // Equality operators (eq, ne)\n const requiresEquality = ['eq', 'ne'].includes(operator)\n\n if (requiresEquality && config?.equality) {\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n return operator === 'eq' ? eq(left, encrypted) : ne(left, encrypted)\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.equality,\n ) as Promise<SQL>\n }\n\n // Fallback to regular Drizzle operators\n return operator === 'eq' ? eq(left, right) : ne(left, right)\n}\n\n/**\n * Creates a range operator (between, notBetween)\n */\nfunction createRangeOperator(\n operator: 'between' | 'notBetween',\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n if (!config?.orderAndRange) {\n return operator === 'between'\n ? between(left, min, max)\n : notBetween(left, min, max)\n }\n\n const executeFn = (\n _encrypted: unknown,\n encryptedMin?: unknown,\n encryptedMax?: unknown,\n ) => {\n if (encryptedMin === undefined || encryptedMax === undefined) {\n throw new EncryptionOperatorError(\n `${operator} operator requires both min and max values`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const rangeCondition = sql`eql_v2.gte(${left}, ${bindIfParam(encryptedMin, left)}) AND eql_v2.lte(${left}, ${bindIfParam(encryptedMax, left)})`\n\n return operator === 'between'\n ? rangeCondition\n : sql`NOT (${rangeCondition})`\n }\n\n return createLazyOperator(\n operator,\n left,\n undefined,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n min,\n max,\n queryTypes.orderAndRange,\n ) as Promise<SQL>\n}\n\n/**\n * Creates a text search operator (like, ilike, notIlike)\n */\nfunction createTextSearchOperator(\n operator: 'like' | 'ilike' | 'notIlike',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<SQL> | SQL {\n const { config } = columnInfo\n\n if (!config?.freeTextSearch) {\n // Cast to satisfy TypeScript\n const rightValue = right as string | SQLWrapper\n switch (operator) {\n case 'like':\n return like(left as Parameters<typeof like>[0], rightValue)\n case 'ilike':\n return ilike(left as Parameters<typeof ilike>[0], rightValue)\n case 'notIlike':\n return notIlike(left as Parameters<typeof notIlike>[0], rightValue)\n }\n }\n\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const sqlFn = sql`eql_v2.${sql.raw(operator === 'notIlike' ? 'ilike' : operator)}(${left}, ${bindIfParam(encrypted, left)})`\n return operator === 'notIlike' ? sql`NOT (${sqlFn})` : sqlFn\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined, // min\n undefined, // max\n queryTypes.freeTextSearch,\n ) as Promise<SQL>\n}\n\n/**\n * Creates a JSONB operator that encrypts a JSON path selector and wraps it\n * in the appropriate `eql_v2` function call.\n *\n * Supports `jsonbPathQueryFirst`, `jsonbGet`, and `jsonbPathExists`.\n * The column must have `searchableJson` enabled in its {@link EncryptedColumnConfig}.\n */\nfunction createJsonbOperator(\n operator: 'jsonbPathQueryFirst' | 'jsonbGet' | 'jsonbPathExists',\n left: SQLWrapper,\n right: unknown,\n columnInfo: ColumnInfo,\n encryptionClient: EncryptionClient,\n defaultTable: EncryptedTable<EncryptedTableColumn> | undefined,\n tableCache: Map<string, EncryptedTable<EncryptedTableColumn>>,\n): Promise<SQL> {\n const { config } = columnInfo\n const encryptedSelector = (value: unknown) =>\n sql`${bindIfParam(value, left)}::eql_v2_encrypted`\n\n if (!config?.searchableJson) {\n throw new EncryptionOperatorError(\n `The ${operator} operator requires searchableJson to be enabled on the column configuration.`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n\n const executeFn = (encrypted: unknown) => {\n if (encrypted === undefined) {\n throw new EncryptionOperatorError(\n `Encryption failed for ${operator} operator`,\n {\n columnName: columnInfo.columnName,\n tableName: columnInfo.tableName,\n operator,\n },\n )\n }\n switch (operator) {\n case 'jsonbPathQueryFirst':\n return sql`eql_v2.jsonb_path_query_first(${left}, ${encryptedSelector(encrypted)})`\n case 'jsonbGet':\n return sql`${left} -> ${encryptedSelector(encrypted)}`\n case 'jsonbPathExists':\n return sql`eql_v2.jsonb_path_exists(${left}, ${encryptedSelector(encrypted)})`\n }\n }\n\n return createLazyOperator(\n operator,\n left,\n right,\n executeFn,\n true,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n undefined,\n undefined,\n queryTypes.steVecSelector,\n ) as Promise<SQL>\n}\n\n// ============================================================================\n// Public API: createEncryptionOperators\n// ============================================================================\n\n/**\n * Creates a set of encryption-aware operators that automatically encrypt values\n * for encrypted columns before using them with Drizzle operators.\n *\n * For equality and text search operators (eq, ne, like, ilike, inArray, etc.):\n * Values are encrypted and then passed to regular Drizzle operators, which use\n * PostgreSQL's built-in operators for eql_v2_encrypted types.\n *\n * For order and range operators (gt, gte, lt, lte, between, notBetween):\n * Values are encrypted and then use eql_v2.* functions (eql_v2.gt(), eql_v2.gte(), etc.)\n * which are required for ORE (Order-Revealing Encryption) comparisons.\n *\n * @param encryptionClient - The EncryptionClient instance\n * @returns An object with all Drizzle operators wrapped for encrypted columns\n *\n * @example\n * ```ts\n * // Initialize operators\n * const ops = createEncryptionOperators(encryptionClient)\n *\n * // Equality search - automatically encrypts and uses PostgreSQL operators\n * const results = await db\n * .select()\n * .from(usersTable)\n * .where(await ops.eq(usersTable.email, 'user@example.com'))\n *\n * // Range query - automatically encrypts and uses eql_v2.gte()\n * const olderUsers = await db\n * .select()\n * .from(usersTable)\n * .where(await ops.gte(usersTable.age, 25))\n * ```\n */\nexport function createEncryptionOperators(encryptionClient: EncryptionClient): {\n // Comparison operators\n /**\n * Equality operator - encrypts value for encrypted columns.\n * Requires either `equality` or `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users with a specific email address.\n * ```ts\n * const condition = await ops.eq(usersTable.email, 'user@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n eq: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Not equal operator - encrypts value for encrypted columns.\n * Requires either `equality` or `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users whose email address is not a specific value.\n * ```ts\n * const condition = await ops.ne(usersTable.email, 'user@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n ne: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Greater than operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users older than a specific age.\n * ```ts\n * const condition = await ops.gt(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n gt: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Greater than or equal operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users older than or equal to a specific age.\n * ```ts\n * const condition = await ops.gte(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n gte: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Less than operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users younger than a specific age.\n * ```ts\n * const condition = await ops.lt(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n lt: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Less than or equal operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users younger than or equal to a specific age.\n * ```ts\n * const condition = await ops.lte(usersTable.age, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n lte: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * Between operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users within a specific age range.\n * ```ts\n * const condition = await ops.between(usersTable.age, 20, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n between: (left: SQLWrapper, min: unknown, max: unknown) => Promise<SQL> | SQL\n\n /**\n * Not between operator for encrypted columns with ORE index.\n * Requires `orderAndRange` to be set on {@link EncryptedColumnConfig}.\n *\n * @example\n * Select users outside a specific age range.\n * ```ts\n * const condition = await ops.notBetween(usersTable.age, 20, 30)\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n notBetween: (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ) => Promise<SQL> | SQL\n\n /**\n * Like operator for encrypted columns with free text search.\n * Requires `freeTextSearch` to be set on {@link EncryptedColumnConfig}.\n *\n * > [!IMPORTANT]\n * > Case sensitivity on encrypted columns depends on the {@link EncryptedColumnConfig}.\n * > Ensure that the column is configured for case-insensitive search if needed.\n *\n * @example\n * Select users with email addresses matching a pattern.\n * ```ts\n * const condition = await ops.like(usersTable.email, '%@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n like: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * ILike operator for encrypted columns with free text search.\n * Requires `freeTextSearch` to be set on {@link EncryptedColumnConfig}.\n *\n * > [!IMPORTANT]\n * > Case sensitivity on encrypted columns depends on the {@link EncryptedColumnConfig}.\n * > Ensure that the column is configured for case-insensitive search if needed.\n *\n * @example\n * Select users with email addresses matching a pattern (case-insensitive).\n * ```ts\n * const condition = await ops.ilike(usersTable.email, '%@example.com')\n * const results = await db.select().from(usersTable).where(condition)\n * ```\n */\n ilike: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n notIlike: (left: SQLWrapper, right: unknown) => Promise<SQL> | SQL\n\n /**\n * JSONB path query first operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and calls `eql_v2.jsonb_path_query_first()`,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbPathQueryFirst: (left: SQLWrapper, right: unknown) => Promise<SQL>\n\n /**\n * JSONB get operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and uses the `->` operator,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbGet: (left: SQLWrapper, right: unknown) => Promise<SQL>\n\n /**\n * JSONB path exists operator for encrypted columns with searchable JSON.\n * Requires `searchableJson` to be set on {@link EncryptedColumnConfig}.\n *\n * Encrypts the JSON path selector and calls `eql_v2.jsonb_path_exists()`,\n * casting the parameter to `eql_v2_encrypted`.\n *\n * @throws {EncryptionOperatorError} If the column does not have `searchableJson` enabled.\n */\n jsonbPathExists: (left: SQLWrapper, right: unknown) => Promise<SQL>\n // Array operators\n inArray: (left: SQLWrapper, right: unknown[] | SQLWrapper) => Promise<SQL>\n notInArray: (left: SQLWrapper, right: unknown[] | SQLWrapper) => Promise<SQL>\n // Sorting operators\n asc: (column: SQLWrapper) => SQL\n desc: (column: SQLWrapper) => SQL\n and: (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ) => Promise<SQL>\n or: (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ) => Promise<SQL>\n // Operators that don't need encryption (pass through to Drizzle)\n exists: typeof exists\n notExists: typeof notExists\n isNull: typeof isNull\n isNotNull: typeof isNotNull\n not: typeof not\n // Array operators that work with arrays directly (not encrypted values)\n arrayContains: typeof arrayContains\n arrayContained: typeof arrayContained\n arrayOverlaps: typeof arrayOverlaps\n} {\n // Create a cache for encrypted tables keyed by table name\n const tableCache = new Map<string, EncryptedTable<EncryptedTableColumn>>()\n const defaultTable: EncryptedTable<EncryptedTableColumn> | undefined =\n undefined\n\n /**\n * Equality operator - encrypts value and uses regular Drizzle operator\n */\n const encryptedEq = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'eq',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not equal operator - encrypts value and uses regular Drizzle operator\n */\n const encryptedNe = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'ne',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Greater than operator - uses eql_v2.gt() for encrypted columns with ORE index\n */\n const encryptedGt = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'gt',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Greater than or equal operator - uses eql_v2.gte() for encrypted columns with ORE index\n */\n const encryptedGte = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'gte',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Less than operator - uses eql_v2.lt() for encrypted columns with ORE index\n */\n const encryptedLt = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'lt',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Less than or equal operator - uses eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedLte = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createComparisonOperator(\n 'lte',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Between operator - uses eql_v2.gte() and eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedBetween = (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createRangeOperator(\n 'between',\n left,\n min,\n max,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not between operator - uses eql_v2.gte() and eql_v2.lte() for encrypted columns with ORE index\n */\n const encryptedNotBetween = (\n left: SQLWrapper,\n min: unknown,\n max: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createRangeOperator(\n 'notBetween',\n left,\n min,\n max,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Like operator - encrypts value and uses eql_v2.like() for encrypted columns with match index\n */\n const encryptedLike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'like',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Case-insensitive like operator - encrypts value and uses eql_v2.ilike() for encrypted columns with match index\n */\n const encryptedIlike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'ilike',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * Not like operator (case insensitive) - encrypts value and uses eql_v2.ilike() for encrypted columns with match index\n */\n const encryptedNotIlike = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> | SQL => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createTextSearchOperator(\n 'notIlike',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB path query first operator - encrypts the selector and calls\n * `eql_v2.jsonb_path_query_first()` for encrypted columns with searchable JSON.\n */\n const encryptedJsonbPathQueryFirst = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbPathQueryFirst',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB get operator - encrypts the selector and uses the `->` operator\n * for encrypted columns with searchable JSON.\n */\n const encryptedJsonbGet = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbGet',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * JSONB path exists operator - encrypts the selector and calls\n * `eql_v2.jsonb_path_exists()` for encrypted columns with searchable JSON.\n */\n const encryptedJsonbPathExists = (\n left: SQLWrapper,\n right: unknown,\n ): Promise<SQL> => {\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n return createJsonbOperator(\n 'jsonbPathExists',\n left,\n right,\n columnInfo,\n encryptionClient,\n defaultTable,\n tableCache,\n )\n }\n\n /**\n * In array operator - encrypts all values in the array\n */\n const encryptedInArray = async (\n left: SQLWrapper,\n right: unknown[] | SQLWrapper,\n ): Promise<SQL> => {\n // If right is a SQLWrapper (subquery), pass through to Drizzle\n if (isSQLWrapper(right)) {\n return inArray(left, right as unknown as Parameters<typeof inArray>[1])\n }\n\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n\n if (!columnInfo.config?.equality || !Array.isArray(right)) {\n return inArray(left, right as unknown[])\n }\n\n // Encrypt all values in the array in a single batch\n const encryptedValues = await encryptValues(\n encryptionClient,\n right.map((value) => ({\n value,\n column: left,\n queryType: queryTypes.equality,\n })),\n defaultTable,\n tableCache,\n )\n\n // Use regular eq for each encrypted value - PostgreSQL operators handle it\n const conditions = encryptedValues\n .filter((encrypted) => encrypted !== undefined)\n .map((encrypted) => eq(left, encrypted))\n\n if (conditions.length === 0) {\n return sql`false`\n }\n\n const combined = or(...conditions)\n return combined ?? sql`false`\n }\n\n /**\n * Not in array operator\n */\n const encryptedNotInArray = async (\n left: SQLWrapper,\n right: unknown[] | SQLWrapper,\n ): Promise<SQL> => {\n // If right is a SQLWrapper (subquery), pass through to Drizzle\n if (isSQLWrapper(right)) {\n return notInArray(\n left,\n right as unknown as Parameters<typeof notInArray>[1],\n )\n }\n\n const columnInfo = getColumnInfo(left, defaultTable, tableCache)\n\n if (!columnInfo.config?.equality || !Array.isArray(right)) {\n return notInArray(left, right as unknown[])\n }\n\n // Encrypt all values in the array in a single batch\n const encryptedValues = await encryptValues(\n encryptionClient,\n right.map((value) => ({\n value,\n column: left,\n queryType: queryTypes.equality,\n })),\n defaultTable,\n tableCache,\n )\n\n // Use regular ne for each encrypted value - PostgreSQL operators handle it\n const conditions = encryptedValues\n .filter((encrypted) => encrypted !== undefined)\n .map((encrypted) => ne(left, encrypted))\n\n if (conditions.length === 0) {\n return sql`true`\n }\n\n const combined = and(...conditions)\n return combined ?? sql`true`\n }\n\n /**\n * Ascending order helper - uses eql_v2.order_by() for encrypted columns with ORE index\n */\n const encryptedAsc = (column: SQLWrapper): SQL => {\n const columnInfo = getColumnInfo(column, defaultTable, tableCache)\n\n if (columnInfo.config?.orderAndRange) {\n return asc(sql`eql_v2.order_by(${column})`)\n }\n\n return asc(column)\n }\n\n /**\n * Descending order helper - uses eql_v2.order_by() for encrypted columns with ORE index\n */\n const encryptedDesc = (column: SQLWrapper): SQL => {\n const columnInfo = getColumnInfo(column, defaultTable, tableCache)\n\n if (columnInfo.config?.orderAndRange) {\n return desc(sql`eql_v2.order_by(${column})`)\n }\n\n return desc(column)\n }\n\n /**\n * Batched AND operator - collects lazy operators, batches encryption, and combines conditions\n */\n const encryptedAnd = async (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ): Promise<SQL> => {\n // Single pass: separate lazy operators from regular conditions\n const lazyOperators: LazyOperator[] = []\n const regularConditions: (SQL | SQLWrapper | undefined)[] = []\n const regularPromises: Promise<SQL>[] = []\n\n for (const condition of conditions) {\n if (condition === undefined) {\n continue\n }\n\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else if (condition instanceof Promise) {\n // Check if promise is also a lazy operator\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else {\n regularPromises.push(condition)\n }\n } else {\n regularConditions.push(condition)\n }\n }\n\n // If there are no lazy operators, just use Drizzle's and()\n if (lazyOperators.length === 0) {\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...(await Promise.all(regularPromises)),\n ]\n return and(...allConditions) ?? sql`true`\n }\n\n // Single pass: collect all values to encrypt with metadata\n const valuesToEncrypt: Array<{\n value: unknown\n column: SQLWrapper\n columnInfo: ColumnInfo\n queryType?: QueryTypeName\n lazyOpIndex: number\n isMin?: boolean\n isMax?: boolean\n }> = []\n\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n if (!lazyOp.needsEncryption) {\n continue\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.min,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMin: true,\n })\n valuesToEncrypt.push({\n value: lazyOp.max,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMax: true,\n })\n } else if (lazyOp.right !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.right,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n })\n }\n }\n\n // Batch encrypt all values\n const encryptedResults = await encryptValues(\n encryptionClient,\n valuesToEncrypt.map((v) => ({\n value: v.value,\n column: v.column,\n queryType: v.queryType,\n })),\n defaultTable,\n tableCache,\n )\n\n // Group encrypted values by lazy operator index\n const encryptedByLazyOp = new Map<\n number,\n { value?: unknown; min?: unknown; max?: unknown }\n >()\n\n for (let i = 0; i < valuesToEncrypt.length; i++) {\n const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i]\n const encrypted = encryptedResults[i]\n\n let group = encryptedByLazyOp.get(lazyOpIndex)\n if (!group) {\n group = {}\n encryptedByLazyOp.set(lazyOpIndex, group)\n }\n\n if (isMin) {\n group.min = encrypted\n } else if (isMax) {\n group.max = encrypted\n } else {\n group.value = encrypted\n }\n }\n\n // Execute all lazy operators with their encrypted values\n const sqlConditions: SQL[] = []\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n const encrypted = encryptedByLazyOp.get(i)\n\n let sqlCondition: SQL\n if (lazyOp.needsEncryption && encrypted) {\n const encryptedValues: Array<{ value: unknown; encrypted: unknown }> =\n []\n if (encrypted.value !== undefined) {\n encryptedValues.push({\n value: lazyOp.right,\n encrypted: encrypted.value,\n })\n }\n if (encrypted.min !== undefined) {\n encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min })\n }\n if (encrypted.max !== undefined) {\n encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max })\n }\n sqlCondition = await executeLazyOperator(lazyOp, encryptedValues)\n } else {\n sqlCondition = lazyOp.execute(lazyOp.right)\n }\n\n sqlConditions.push(sqlCondition)\n }\n\n // Await any regular promises\n const regularPromisesResults = await Promise.all(regularPromises)\n\n // Combine all conditions\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...sqlConditions,\n ...regularPromisesResults,\n ]\n\n return and(...allConditions) ?? sql`true`\n }\n\n /**\n * Batched OR operator - collects lazy operators, batches encryption, and combines conditions\n */\n const encryptedOr = async (\n ...conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[]\n ): Promise<SQL> => {\n const lazyOperators: LazyOperator[] = []\n const regularConditions: (SQL | SQLWrapper | undefined)[] = []\n const regularPromises: Promise<SQL>[] = []\n\n for (const condition of conditions) {\n if (condition === undefined) {\n continue\n }\n\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else if (condition instanceof Promise) {\n if (isLazyOperator(condition)) {\n lazyOperators.push(condition)\n } else {\n regularPromises.push(condition)\n }\n } else {\n regularConditions.push(condition)\n }\n }\n\n if (lazyOperators.length === 0) {\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...(await Promise.all(regularPromises)),\n ]\n return or(...allConditions) ?? sql`false`\n }\n\n const valuesToEncrypt: Array<{\n value: unknown\n column: SQLWrapper\n columnInfo: ColumnInfo\n queryType?: QueryTypeName\n lazyOpIndex: number\n isMin?: boolean\n isMax?: boolean\n }> = []\n\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n if (!lazyOp.needsEncryption) {\n continue\n }\n\n if (lazyOp.min !== undefined && lazyOp.max !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.min,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMin: true,\n })\n valuesToEncrypt.push({\n value: lazyOp.max,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n isMax: true,\n })\n } else if (lazyOp.right !== undefined) {\n valuesToEncrypt.push({\n value: lazyOp.right,\n column: lazyOp.left,\n columnInfo: lazyOp.columnInfo,\n queryType: lazyOp.queryType,\n lazyOpIndex: i,\n })\n }\n }\n\n const encryptedResults = await encryptValues(\n encryptionClient,\n valuesToEncrypt.map((v) => ({\n value: v.value,\n column: v.column,\n queryType: v.queryType,\n })),\n defaultTable,\n tableCache,\n )\n\n const encryptedByLazyOp = new Map<\n number,\n { value?: unknown; min?: unknown; max?: unknown }\n >()\n\n for (let i = 0; i < valuesToEncrypt.length; i++) {\n const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i]\n const encrypted = encryptedResults[i]\n\n let group = encryptedByLazyOp.get(lazyOpIndex)\n if (!group) {\n group = {}\n encryptedByLazyOp.set(lazyOpIndex, group)\n }\n\n if (isMin) {\n group.min = encrypted\n } else if (isMax) {\n group.max = encrypted\n } else {\n group.value = encrypted\n }\n }\n\n const sqlConditions: SQL[] = []\n for (let i = 0; i < lazyOperators.length; i++) {\n const lazyOp = lazyOperators[i]\n const encrypted = encryptedByLazyOp.get(i)\n\n let sqlCondition: SQL\n if (lazyOp.needsEncryption && encrypted) {\n const encryptedValues: Array<{ value: unknown; encrypted: unknown }> =\n []\n if (encrypted.value !== undefined) {\n encryptedValues.push({\n value: lazyOp.right,\n encrypted: encrypted.value,\n })\n }\n if (encrypted.min !== undefined) {\n encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min })\n }\n if (encrypted.max !== undefined) {\n encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max })\n }\n sqlCondition = await executeLazyOperator(lazyOp, encryptedValues)\n } else {\n sqlCondition = lazyOp.execute(lazyOp.right)\n }\n\n sqlConditions.push(sqlCondition)\n }\n\n const regularPromisesResults = await Promise.all(regularPromises)\n\n const allConditions: (SQL | SQLWrapper | undefined)[] = [\n ...regularConditions,\n ...sqlConditions,\n ...regularPromisesResults,\n ]\n\n return or(...allConditions) ?? sql`false`\n }\n\n return {\n // Comparison operators\n eq: encryptedEq,\n ne: encryptedNe,\n gt: encryptedGt,\n gte: encryptedGte,\n lt: encryptedLt,\n lte: encryptedLte,\n\n // Range operators\n between: encryptedBetween,\n notBetween: encryptedNotBetween,\n\n // Text search operators\n like: encryptedLike,\n ilike: encryptedIlike,\n notIlike: encryptedNotIlike,\n\n // Searchable JSON operators\n jsonbPathQueryFirst: encryptedJsonbPathQueryFirst,\n jsonbGet: encryptedJsonbGet,\n jsonbPathExists: encryptedJsonbPathExists,\n\n // Array operators\n inArray: encryptedInArray,\n notInArray: encryptedNotInArray,\n\n // Sorting operators\n asc: encryptedAsc,\n desc: encryptedDesc,\n\n // AND operator - batches encryption operations\n and: encryptedAnd,\n\n // OR operator - batches encryption operations\n or: encryptedOr,\n\n // Operators that don't need encryption (pass through to Drizzle)\n exists,\n notExists,\n isNull,\n isNotNull,\n not,\n // Array operators that work with arrays directly (not encrypted values)\n arrayContains,\n arrayContained,\n arrayOverlaps,\n }\n}\n"],"mappings":"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","names":["encryptedTable","config","encryptedColumn","sql","allConditions"]}