@cipherstash/stack 0.7.0 → 0.9.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.
- package/CHANGELOG.md +12 -0
- package/README.md +33 -3
- package/dist/bin/stash.js +419 -204
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-URZNWMOO.js → chunk-3BOJHROP.js} +3 -3
- package/dist/{chunk-H7IHWDZI.js → chunk-4C52Q5R6.js} +2 -2
- package/dist/{chunk-Y35W4WFN.js → chunk-Y3KSTOVR.js} +35 -4
- package/dist/chunk-Y3KSTOVR.js.map +1 -0
- package/dist/{client-DQMy1ux5.d.cts → client-CV7X5Hrt.d.cts} +1 -1
- package/dist/{client-zxrOpegN.d.ts → client-_63nbmO7.d.ts} +1 -1
- package/dist/client.cjs +14 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +14 -3
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +2 -2
- package/dist/drizzle/index.d.ts +2 -2
- package/dist/drizzle/index.js +1 -1
- package/dist/dynamodb/index.d.cts +2 -2
- package/dist/dynamodb/index.d.ts +2 -2
- package/dist/encryption/index.cjs +11 -0
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +2 -2
- package/dist/encryption/index.d.ts +2 -2
- package/dist/encryption/index.js +2 -2
- package/dist/index.cjs +14 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/schema/index.cjs +38 -5
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +7 -3
- package/dist/secrets/index.cjs +14 -3
- package/dist/secrets/index.cjs.map +1 -1
- package/dist/secrets/index.d.cts +1 -1
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/index.js +3 -3
- package/dist/supabase/index.cjs +28 -5
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +2 -2
- package/dist/supabase/index.d.ts +2 -2
- package/dist/supabase/index.js +17 -5
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-07ilcGY-.d.ts → types-public-B5YxQhR6.d.cts} +25 -9
- package/dist/{types-public-07ilcGY-.d.cts → types-public-B5YxQhR6.d.ts} +25 -9
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-Y35W4WFN.js.map +0 -1
- /package/dist/{chunk-URZNWMOO.js.map → chunk-3BOJHROP.js.map} +0 -0
- /package/dist/{chunk-H7IHWDZI.js.map → chunk-4C52Q5R6.js.map} +0 -0
package/dist/supabase/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../chunk-4RNBI3UH.js";
|
|
5
5
|
import {
|
|
6
6
|
EncryptedColumn
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-Y3KSTOVR.js";
|
|
8
8
|
import {
|
|
9
9
|
logger
|
|
10
10
|
} from "../chunk-Q5FTQLYG.js";
|
|
@@ -83,14 +83,18 @@ function splitOrString(input) {
|
|
|
83
83
|
const parts = [];
|
|
84
84
|
let current = "";
|
|
85
85
|
let depth = 0;
|
|
86
|
+
let inQuotes = false;
|
|
86
87
|
for (const char of input) {
|
|
87
|
-
if (char === "
|
|
88
|
+
if (char === '"' && depth === 0) {
|
|
89
|
+
inQuotes = !inQuotes;
|
|
90
|
+
current += char;
|
|
91
|
+
} else if (char === "(" && !inQuotes) {
|
|
88
92
|
depth++;
|
|
89
93
|
current += char;
|
|
90
|
-
} else if (char === ")") {
|
|
94
|
+
} else if (char === ")" && !inQuotes) {
|
|
91
95
|
depth--;
|
|
92
96
|
current += char;
|
|
93
|
-
} else if (char === "," && depth === 0) {
|
|
97
|
+
} else if (char === "," && depth === 0 && !inQuotes) {
|
|
94
98
|
parts.push(current);
|
|
95
99
|
current = "";
|
|
96
100
|
} else {
|
|
@@ -103,6 +107,9 @@ function splitOrString(input) {
|
|
|
103
107
|
return parts;
|
|
104
108
|
}
|
|
105
109
|
function parseOrValue(value) {
|
|
110
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
111
|
+
return value.slice(1, -1);
|
|
112
|
+
}
|
|
106
113
|
if (value.startsWith("(") && value.endsWith(")")) {
|
|
107
114
|
return value.slice(1, -1).split(",").map((v) => v.trim());
|
|
108
115
|
}
|
|
@@ -111,6 +118,7 @@ function parseOrValue(value) {
|
|
|
111
118
|
if (value === "null") return null;
|
|
112
119
|
return value;
|
|
113
120
|
}
|
|
121
|
+
var POSTGREST_RESERVED = /[,().]/;
|
|
114
122
|
function formatOrValue(value) {
|
|
115
123
|
if (Array.isArray(value)) {
|
|
116
124
|
return `(${value.join(",")})`;
|
|
@@ -118,7 +126,11 @@ function formatOrValue(value) {
|
|
|
118
126
|
if (value === null) return "null";
|
|
119
127
|
if (value === true) return "true";
|
|
120
128
|
if (value === false) return "false";
|
|
121
|
-
|
|
129
|
+
const str = String(value);
|
|
130
|
+
if (POSTGREST_RESERVED.test(str)) {
|
|
131
|
+
return `"${str}"`;
|
|
132
|
+
}
|
|
133
|
+
return str;
|
|
122
134
|
}
|
|
123
135
|
|
|
124
136
|
// src/supabase/query-builder.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/supabase/helpers.ts","../../src/supabase/query-builder.ts","../../src/supabase/index.ts"],"sourcesContent":["import type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport type { QueryTypeName } from '@/types'\nimport type { FilterOp, PendingOrCondition } from './types'\n\n/**\n * Get the names of all encrypted columns defined in a table schema.\n */\nexport function getEncryptedColumnNames(\n schema: EncryptedTable<EncryptedTableColumn>,\n): string[] {\n const built = schema.build()\n return Object.keys(built.columns)\n}\n\n/**\n * Check whether a column name refers to an encrypted column in the schema.\n */\nexport function isEncryptedColumn(\n columnName: string,\n encryptedColumnNames: string[],\n): boolean {\n return encryptedColumnNames.includes(columnName)\n}\n\n/**\n * Parse a Supabase select string and add `::jsonb` casts to encrypted columns.\n *\n * Input: `'id, email, name'`\n * Output: `'id, email::jsonb, name::jsonb'` (if email and name are encrypted)\n *\n * Handles whitespace, already-cast columns, and embedded functions.\n */\nexport function addJsonbCasts(\n columns: string,\n encryptedColumnNames: string[],\n): string {\n return columns\n .split(',')\n .map((col) => {\n const trimmed = col.trim()\n\n // Skip empty segments\n if (!trimmed) return col\n\n // If it already has a cast (e.g. `email::jsonb`), skip\n if (trimmed.includes('::')) return col\n\n // If it contains parens (function call) or dots (foreign table), skip\n if (trimmed.includes('(') || trimmed.includes('.')) return col\n\n // Check if the column name (possibly with alias) is encrypted\n // Handle `column_name` or `column_name as alias`\n const parts = trimmed.split(/\\s+/)\n const colName = parts[0]\n\n if (isEncryptedColumn(colName, encryptedColumnNames)) {\n // Preserve original whitespace before the column\n const leadingWhitespace = col.match(/^(\\s*)/)?.[1] ?? ''\n if (parts.length > 1) {\n // Has alias: `email as e` -> `email::jsonb as e`\n return `${leadingWhitespace}${colName}::jsonb ${parts.slice(1).join(' ')}`\n }\n return `${leadingWhitespace}${colName}::jsonb`\n }\n\n return col\n })\n .join(',')\n}\n\n/**\n * Map a Supabase filter operation to a CipherStash query type.\n */\nexport function mapFilterOpToQueryType(op: FilterOp): QueryTypeName {\n switch (op) {\n case 'eq':\n case 'neq':\n case 'in':\n case 'is':\n return 'equality'\n case 'like':\n case 'ilike':\n return 'freeTextSearch'\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte':\n return 'orderAndRange'\n default:\n return 'equality'\n }\n}\n\n/**\n * Parse a Supabase `.or()` filter string into structured conditions.\n *\n * Input: `'email.eq.john@example.com,name.ilike.%john%'`\n * Output: `[{ column: 'email', op: 'eq', value: 'john@example.com' }, { column: 'name', op: 'ilike', value: '%john%' }]`\n */\nexport function parseOrString(orString: string): PendingOrCondition[] {\n const conditions: PendingOrCondition[] = []\n // Split on commas that are not inside parentheses (nested or/and)\n const parts = splitOrString(orString)\n\n for (const part of parts) {\n const trimmed = part.trim()\n if (!trimmed) continue\n\n // Format: column.op.value\n const firstDot = trimmed.indexOf('.')\n if (firstDot === -1) continue\n\n const column = trimmed.slice(0, firstDot)\n const rest = trimmed.slice(firstDot + 1)\n\n const secondDot = rest.indexOf('.')\n if (secondDot === -1) continue\n\n const op = rest.slice(0, secondDot) as FilterOp\n const value = rest.slice(secondDot + 1)\n\n // Handle special value formats\n const parsedValue = parseOrValue(value)\n\n conditions.push({ column, op, value: parsedValue })\n }\n\n return conditions\n}\n\n/**\n * Rebuild an `.or()` string from structured conditions.\n */\nexport function rebuildOrString(conditions: PendingOrCondition[]): string {\n return conditions\n .map((c) => {\n const value = formatOrValue(c.value)\n return `${c.column}.${c.op}.${value}`\n })\n .join(',')\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction splitOrString(input: string): string[] {\n const parts: string[] = []\n let current = ''\n let depth = 0\n\n for (const char of input) {\n if (char === '(') {\n depth++\n current += char\n } else if (char === ')') {\n depth--\n current += char\n } else if (char === ',' && depth === 0) {\n parts.push(current)\n current = ''\n } else {\n current += char\n }\n }\n\n if (current) {\n parts.push(current)\n }\n\n return parts\n}\n\nfunction parseOrValue(value: string): unknown {\n // Handle parenthesized lists: (val1,val2,val3)\n if (value.startsWith('(') && value.endsWith(')')) {\n return value\n .slice(1, -1)\n .split(',')\n .map((v) => v.trim())\n }\n\n // Handle booleans\n if (value === 'true') return true\n if (value === 'false') return false\n\n // Handle null\n if (value === 'null') return null\n\n return value\n}\n\nfunction formatOrValue(value: unknown): string {\n if (Array.isArray(value)) {\n return `(${value.join(',')})`\n }\n if (value === null) return 'null'\n if (value === true) return 'true'\n if (value === false) return 'false'\n return String(value)\n}\n","import type { EncryptionClient } from '@/encryption'\nimport {\n bulkModelsToEncryptedPgComposites,\n modelToEncryptedPgComposites,\n} from '@/encryption/helpers'\nimport type { AuditConfig } from '@/encryption/operations/base-operation'\nimport type { LockContext } from '@/identity'\nimport type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport { EncryptedColumn } from '@/schema'\nimport type { ScalarQueryTerm } from '@/types'\nimport { logger } from '@/utils/logger'\nimport type { JsPlaintext } from '@cipherstash/protect-ffi'\nimport {\n addJsonbCasts,\n getEncryptedColumnNames,\n isEncryptedColumn,\n mapFilterOpToQueryType,\n parseOrString,\n rebuildOrString,\n} from './helpers'\nimport type {\n EncryptedSupabaseError,\n EncryptedSupabaseResponse,\n FilterOp,\n MutationOp,\n PendingFilter,\n PendingMatchFilter,\n PendingNotFilter,\n PendingOrCondition,\n PendingOrFilter,\n PendingRawFilter,\n ResultMode,\n SupabaseClientLike,\n SupabaseQueryBuilder,\n TransformOp,\n} from './types'\n\n/**\n * A deferred query builder that wraps Supabase's query builder to automatically\n * handle encryption and decryption of data.\n *\n * All chained operations are recorded synchronously. When the builder is awaited,\n * it encrypts mutation data, adds `::jsonb` casts, batch-encrypts filter values,\n * executes the real Supabase query, and decrypts results.\n */\nexport class EncryptedQueryBuilderImpl<\n T extends Record<string, unknown> = Record<string, unknown>,\n> {\n private tableName: string\n private schema: EncryptedTable<EncryptedTableColumn>\n private encryptionClient: EncryptionClient\n private supabaseClient: SupabaseClientLike\n private encryptedColumnNames: string[]\n\n // Recorded operations\n private mutation: MutationOp | null = null\n private selectColumns: string | null = null\n private selectOptions:\n | { head?: boolean; count?: 'exact' | 'planned' | 'estimated' }\n | undefined = undefined\n private filters: PendingFilter[] = []\n private orFilters: PendingOrFilter[] = []\n private matchFilters: PendingMatchFilter[] = []\n private notFilters: PendingNotFilter[] = []\n private rawFilters: PendingRawFilter[] = []\n private transforms: TransformOp[] = []\n private resultMode: ResultMode = 'array'\n private shouldThrowOnError = false\n\n // Encryption-specific state\n private lockContext: LockContext | null = null\n private auditConfig: AuditConfig | null = null\n\n constructor(\n tableName: string,\n schema: EncryptedTable<EncryptedTableColumn>,\n encryptionClient: EncryptionClient,\n supabaseClient: SupabaseClientLike,\n ) {\n this.tableName = tableName\n this.schema = schema\n this.encryptionClient = encryptionClient\n this.supabaseClient = supabaseClient\n this.encryptedColumnNames = getEncryptedColumnNames(schema)\n }\n\n // ---------------------------------------------------------------------------\n // Mutation methods\n // ---------------------------------------------------------------------------\n\n select(\n columns: string,\n options?: { head?: boolean; count?: 'exact' | 'planned' | 'estimated' },\n ): this {\n if (columns === '*') {\n throw new Error(\n \"encryptedSupabase does not support select('*'). Please list columns explicitly so that encrypted columns can be cast with ::jsonb.\",\n )\n }\n this.selectColumns = columns\n this.selectOptions = options\n return this\n }\n\n insert(\n data: Partial<T> | Partial<T>[],\n options?: {\n count?: 'exact' | 'planned' | 'estimated'\n defaultToNull?: boolean\n onConflict?: string\n },\n ): this {\n this.mutation = {\n kind: 'insert',\n data: data as Record<string, unknown> | Record<string, unknown>[],\n options,\n }\n return this\n }\n\n update(\n data: Partial<T>,\n options?: { count?: 'exact' | 'planned' | 'estimated' },\n ): this {\n this.mutation = {\n kind: 'update',\n data: data as Record<string, unknown>,\n options,\n }\n return this\n }\n\n upsert(\n data: Partial<T> | Partial<T>[],\n options?: {\n count?: 'exact' | 'planned' | 'estimated'\n onConflict?: string\n ignoreDuplicates?: boolean\n defaultToNull?: boolean\n },\n ): this {\n this.mutation = {\n kind: 'upsert',\n data: data as Record<string, unknown> | Record<string, unknown>[],\n options,\n }\n return this\n }\n\n delete(options?: { count?: 'exact' | 'planned' | 'estimated' }): this {\n this.mutation = { kind: 'delete', options }\n return this\n }\n\n // ---------------------------------------------------------------------------\n // Filter methods\n // ---------------------------------------------------------------------------\n\n eq(column: string, value: unknown): this {\n this.filters.push({ op: 'eq', column, value })\n return this\n }\n\n neq(column: string, value: unknown): this {\n this.filters.push({ op: 'neq', column, value })\n return this\n }\n\n gt(column: string, value: unknown): this {\n this.filters.push({ op: 'gt', column, value })\n return this\n }\n\n gte(column: string, value: unknown): this {\n this.filters.push({ op: 'gte', column, value })\n return this\n }\n\n lt(column: string, value: unknown): this {\n this.filters.push({ op: 'lt', column, value })\n return this\n }\n\n lte(column: string, value: unknown): this {\n this.filters.push({ op: 'lte', column, value })\n return this\n }\n\n like(column: string, pattern: string): this {\n this.filters.push({ op: 'like', column, value: pattern })\n return this\n }\n\n ilike(column: string, pattern: string): this {\n this.filters.push({ op: 'ilike', column, value: pattern })\n return this\n }\n\n is(column: string, value: null | boolean): this {\n this.filters.push({ op: 'is', column, value })\n return this\n }\n\n in(column: string, values: unknown[]): this {\n this.filters.push({ op: 'in', column, value: values })\n return this\n }\n\n filter(column: string, operator: string, value: unknown): this {\n this.rawFilters.push({ column, operator, value })\n return this\n }\n\n not(column: string, operator: string, value: unknown): this {\n this.notFilters.push({ column, op: operator as FilterOp, value })\n return this\n }\n\n or(\n filtersOrConditions: string | PendingOrCondition[],\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n if (typeof filtersOrConditions === 'string') {\n this.orFilters.push({\n kind: 'string',\n value: filtersOrConditions,\n referencedTable: options?.referencedTable ?? options?.foreignTable,\n })\n } else {\n this.orFilters.push({\n kind: 'structured',\n conditions: filtersOrConditions,\n })\n }\n return this\n }\n\n match(query: Record<string, unknown>): this {\n this.matchFilters.push({ query })\n return this\n }\n\n // ---------------------------------------------------------------------------\n // Transform methods (passthrough)\n // ---------------------------------------------------------------------------\n\n order(\n column: string,\n options?: {\n ascending?: boolean\n nullsFirst?: boolean\n referencedTable?: string\n foreignTable?: string\n },\n ): this {\n this.transforms.push({ kind: 'order', column, options })\n return this\n }\n\n limit(\n count: number,\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n this.transforms.push({ kind: 'limit', count, options })\n return this\n }\n\n range(\n from: number,\n to: number,\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n this.transforms.push({ kind: 'range', from, to, options })\n return this\n }\n\n single(): this {\n this.resultMode = 'single'\n this.transforms.push({ kind: 'single' })\n return this\n }\n\n maybeSingle(): this {\n this.resultMode = 'maybeSingle'\n this.transforms.push({ kind: 'maybeSingle' })\n return this\n }\n\n csv(): this {\n this.transforms.push({ kind: 'csv' })\n return this\n }\n\n abortSignal(signal: AbortSignal): this {\n this.transforms.push({ kind: 'abortSignal', signal })\n return this\n }\n\n throwOnError(): this {\n this.shouldThrowOnError = true\n this.transforms.push({ kind: 'throwOnError' })\n return this\n }\n\n returns<U extends Record<string, unknown>>(): EncryptedQueryBuilderImpl<U> {\n // Type-level cast only; builder state is preserved\n return this as unknown as EncryptedQueryBuilderImpl<U>\n }\n\n // ---------------------------------------------------------------------------\n // Encryption-specific methods\n // ---------------------------------------------------------------------------\n\n withLockContext(lockContext: LockContext): this {\n this.lockContext = lockContext\n return this\n }\n\n audit(config: AuditConfig): this {\n this.auditConfig = config\n return this\n }\n\n // ---------------------------------------------------------------------------\n // PromiseLike implementation (deferred execution)\n // ---------------------------------------------------------------------------\n\n then<TResult1 = EncryptedSupabaseResponse<T[]>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: EncryptedSupabaseResponse<T[]>,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected)\n }\n\n // ---------------------------------------------------------------------------\n // Core execution\n // ---------------------------------------------------------------------------\n\n private async execute(): Promise<EncryptedSupabaseResponse<T[]>> {\n try {\n logger.debug(`Supabase encrypted query on table \"${this.tableName}\".`)\n\n // 1. Encrypt mutation data\n const encryptedMutation = await this.encryptMutationData()\n\n // 2. Build select string with ::jsonb casts\n const selectString = this.buildSelectString()\n\n // 3. Batch-encrypt filter values\n const encryptedFilters = await this.encryptFilterValues()\n\n // 4. Build and execute real Supabase query\n const result = await this.buildAndExecuteQuery(\n encryptedMutation,\n selectString,\n encryptedFilters,\n )\n\n // 5. Decrypt results\n return await this.decryptResults(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.error(\n `Supabase encrypted query failed on table \"${this.tableName}\": ${message}`,\n )\n\n const error: EncryptedSupabaseError = {\n message,\n encryptionError: undefined,\n }\n\n if (this.shouldThrowOnError) {\n throw err\n }\n\n return {\n data: null,\n error,\n count: null,\n status: 500,\n statusText: 'Encryption Error',\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Step 1: Encrypt mutation data\n // ---------------------------------------------------------------------------\n\n private async encryptMutationData(): Promise<\n Record<string, unknown> | Record<string, unknown>[] | null\n > {\n if (!this.mutation) return null\n\n if (this.mutation.kind === 'delete') return null\n\n const data = this.mutation.data\n\n if (Array.isArray(data)) {\n // Bulk encrypt\n const baseOp = this.encryptionClient.bulkEncryptModels(data, this.schema)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt models for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt models: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return bulkModelsToEncryptedPgComposites(result.data)\n }\n\n // Single model\n const baseOp = this.encryptionClient.encryptModel(data, this.schema)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt model for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt model: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return modelToEncryptedPgComposites(result.data)\n }\n\n // ---------------------------------------------------------------------------\n // Step 2: Build select string with casts\n // ---------------------------------------------------------------------------\n\n private buildSelectString(): string | null {\n if (this.selectColumns === null) return null\n return addJsonbCasts(this.selectColumns, this.encryptedColumnNames)\n }\n\n // ---------------------------------------------------------------------------\n // Step 3: Encrypt filter values\n // ---------------------------------------------------------------------------\n\n private async encryptFilterValues(): Promise<EncryptedFilterState> {\n // Collect all terms that need encryption\n const terms: ScalarQueryTerm[] = []\n const termMap: TermMapping[] = []\n\n const tableColumns = this.getColumnMap()\n\n // Regular filters\n for (let i = 0; i < this.filters.length; i++) {\n const f = this.filters[i]\n if (!isEncryptedColumn(f.column, this.encryptedColumnNames)) continue\n\n const column = tableColumns[f.column]\n if (!column) continue\n\n if (f.op === 'in' && Array.isArray(f.value)) {\n // For `in` filters, encrypt each value separately\n for (let j = 0; j < f.value.length; j++) {\n terms.push({\n value: f.value[j] as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(f.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'filter', filterIndex: i, inIndex: j })\n }\n } else if (f.op === 'is') {\n // `is` is used for null/boolean checks — don't encrypt\n continue\n } else {\n terms.push({\n value: f.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(f.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'filter', filterIndex: i })\n }\n }\n\n // Match filters\n for (let i = 0; i < this.matchFilters.length; i++) {\n const mf = this.matchFilters[i]\n for (const [colName, value] of Object.entries(mf.query)) {\n if (!isEncryptedColumn(colName, this.encryptedColumnNames)) continue\n const column = tableColumns[colName]\n if (!column) continue\n\n terms.push({\n value: value as JsPlaintext,\n column,\n table: this.schema,\n queryType: 'equality',\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'match', matchIndex: i, column: colName })\n }\n }\n\n // Not filters\n for (let i = 0; i < this.notFilters.length; i++) {\n const nf = this.notFilters[i]\n if (!isEncryptedColumn(nf.column, this.encryptedColumnNames)) continue\n const column = tableColumns[nf.column]\n if (!column) continue\n\n terms.push({\n value: nf.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(nf.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'not', notIndex: i })\n }\n\n // Or filters (string form parsed into conditions)\n for (let i = 0; i < this.orFilters.length; i++) {\n const of_ = this.orFilters[i]\n if (of_.kind === 'string') {\n const parsed = parseOrString(of_.value)\n for (let j = 0; j < parsed.length; j++) {\n const cond = parsed[j]\n if (!isEncryptedColumn(cond.column, this.encryptedColumnNames))\n continue\n const column = tableColumns[cond.column]\n if (!column) continue\n\n terms.push({\n value: cond.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(cond.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'or-string', orIndex: i, conditionIndex: j })\n }\n } else {\n for (let j = 0; j < of_.conditions.length; j++) {\n const cond = of_.conditions[j]\n if (!isEncryptedColumn(cond.column, this.encryptedColumnNames))\n continue\n const column = tableColumns[cond.column]\n if (!column) continue\n\n terms.push({\n value: cond.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(cond.op),\n returnType: 'composite-literal',\n })\n termMap.push({\n source: 'or-structured',\n orIndex: i,\n conditionIndex: j,\n })\n }\n }\n }\n\n // Raw filters\n for (let i = 0; i < this.rawFilters.length; i++) {\n const rf = this.rawFilters[i]\n if (!isEncryptedColumn(rf.column, this.encryptedColumnNames)) continue\n const column = tableColumns[rf.column]\n if (!column) continue\n\n terms.push({\n value: rf.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: 'equality',\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'raw', rawIndex: i })\n }\n\n if (terms.length === 0) {\n return { encryptedValues: [], termMap: [] }\n }\n\n // Batch encrypt all terms in one call\n const baseOp = this.encryptionClient.encryptQuery(terms)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt query terms for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt query terms: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return { encryptedValues: result.data, termMap }\n }\n\n // ---------------------------------------------------------------------------\n // Step 4: Build and execute real Supabase query\n // ---------------------------------------------------------------------------\n\n private async buildAndExecuteQuery(\n encryptedMutation:\n | Record<string, unknown>\n | Record<string, unknown>[]\n | null,\n selectString: string | null,\n encryptedFilters: EncryptedFilterState,\n ): Promise<RawSupabaseResult> {\n let query: SupabaseQueryBuilder = this.supabaseClient.from(this.tableName)\n\n // Apply mutation\n if (this.mutation) {\n switch (this.mutation.kind) {\n case 'insert':\n query = query.insert(encryptedMutation!, this.mutation.options)\n break\n case 'update':\n query = query.update(encryptedMutation!, this.mutation.options)\n break\n case 'upsert':\n query = query.upsert(encryptedMutation!, this.mutation.options)\n break\n case 'delete':\n query = query.delete(this.mutation.options)\n break\n }\n }\n\n // Apply select\n if (selectString !== null) {\n query = query.select(selectString, this.selectOptions)\n } else if (!this.mutation) {\n // Default select without explicit columns - shouldn't happen but fallback\n query = query.select('*', this.selectOptions)\n }\n\n // Apply resolved filters\n query = this.applyFilters(query, encryptedFilters)\n\n // Apply transforms\n for (const t of this.transforms) {\n switch (t.kind) {\n case 'order':\n query = query.order(t.column, t.options)\n break\n case 'limit':\n query = query.limit(t.count, t.options)\n break\n case 'range':\n query = query.range(t.from, t.to, t.options)\n break\n case 'single':\n query = query.single()\n break\n case 'maybeSingle':\n query = query.maybeSingle()\n break\n case 'csv':\n query = query.csv()\n break\n case 'abortSignal':\n query = query.abortSignal(t.signal)\n break\n case 'throwOnError':\n query = query.throwOnError()\n break\n }\n }\n\n const result = (await query) as unknown as RawSupabaseResult\n return result\n }\n\n // ---------------------------------------------------------------------------\n // Apply filters with encrypted values substituted\n // ---------------------------------------------------------------------------\n\n private applyFilters(\n query: SupabaseQueryBuilder,\n encryptedFilters: EncryptedFilterState,\n ): SupabaseQueryBuilder {\n let q = query\n\n // Build lookup maps for quick access to encrypted values\n const filterValueMap = new Map<number, unknown>()\n const filterInMap = new Map<string, unknown>() // \"filterIndex:inIndex\" -> value\n const matchValueMap = new Map<string, unknown>() // \"matchIndex:column\" -> value\n const notValueMap = new Map<number, unknown>()\n const rawValueMap = new Map<number, unknown>()\n const orStringConditionMap = new Map<string, unknown>() // \"orIndex:condIndex\" -> value\n const orStructuredConditionMap = new Map<string, unknown>()\n\n for (let i = 0; i < encryptedFilters.termMap.length; i++) {\n const mapping = encryptedFilters.termMap[i]\n const encValue = encryptedFilters.encryptedValues[i]\n\n switch (mapping.source) {\n case 'filter':\n if (mapping.inIndex !== undefined) {\n filterInMap.set(\n `${mapping.filterIndex}:${mapping.inIndex}`,\n encValue,\n )\n } else {\n filterValueMap.set(mapping.filterIndex, encValue)\n }\n break\n case 'match':\n matchValueMap.set(`${mapping.matchIndex}:${mapping.column}`, encValue)\n break\n case 'not':\n notValueMap.set(mapping.notIndex, encValue)\n break\n case 'raw':\n rawValueMap.set(mapping.rawIndex, encValue)\n break\n case 'or-string':\n orStringConditionMap.set(\n `${mapping.orIndex}:${mapping.conditionIndex}`,\n encValue,\n )\n break\n case 'or-structured':\n orStructuredConditionMap.set(\n `${mapping.orIndex}:${mapping.conditionIndex}`,\n encValue,\n )\n break\n }\n }\n\n // Apply regular filters\n for (let i = 0; i < this.filters.length; i++) {\n const f = this.filters[i]\n let value = f.value\n\n if (filterValueMap.has(i)) {\n value = filterValueMap.get(i)\n } else if (f.op === 'in' && Array.isArray(f.value)) {\n // Reconstruct array with encrypted values substituted\n value = f.value.map((v, j) => {\n const key = `${i}:${j}`\n return filterInMap.has(key) ? filterInMap.get(key) : v\n })\n }\n\n switch (f.op) {\n case 'eq':\n q = q.eq(f.column, value)\n break\n case 'neq':\n q = q.neq(f.column, value)\n break\n case 'gt':\n q = q.gt(f.column, value)\n break\n case 'gte':\n q = q.gte(f.column, value)\n break\n case 'lt':\n q = q.lt(f.column, value)\n break\n case 'lte':\n q = q.lte(f.column, value)\n break\n case 'like':\n q = q.like(f.column, value as string)\n break\n case 'ilike':\n q = q.ilike(f.column, value as string)\n break\n case 'is':\n q = q.is(f.column, value)\n break\n case 'in':\n q = q.in(f.column, value as unknown[])\n break\n }\n }\n\n // Apply match filters\n for (let i = 0; i < this.matchFilters.length; i++) {\n const mf = this.matchFilters[i]\n const resolvedQuery: Record<string, unknown> = {}\n\n for (const [colName, originalValue] of Object.entries(mf.query)) {\n const key = `${i}:${colName}`\n resolvedQuery[colName] = matchValueMap.has(key)\n ? matchValueMap.get(key)\n : originalValue\n }\n\n q = q.match(resolvedQuery)\n }\n\n // Apply not filters\n for (let i = 0; i < this.notFilters.length; i++) {\n const nf = this.notFilters[i]\n const value = notValueMap.has(i) ? notValueMap.get(i) : nf.value\n q = q.not(nf.column, nf.op, value)\n }\n\n // Apply or filters\n for (let i = 0; i < this.orFilters.length; i++) {\n const of_ = this.orFilters[i]\n\n if (of_.kind === 'string') {\n const parsed = parseOrString(of_.value)\n let hasEncrypted = false\n\n for (let j = 0; j < parsed.length; j++) {\n const key = `${i}:${j}`\n if (orStringConditionMap.has(key)) {\n parsed[j] = { ...parsed[j], value: orStringConditionMap.get(key) }\n hasEncrypted = true\n }\n }\n\n if (hasEncrypted) {\n q = q.or(rebuildOrString(parsed), {\n referencedTable: of_.referencedTable,\n })\n } else {\n q = q.or(of_.value, { referencedTable: of_.referencedTable })\n }\n } else {\n // Structured: convert to string\n const conditions = of_.conditions.map((cond, j) => {\n const key = `${i}:${j}`\n if (orStructuredConditionMap.has(key)) {\n return { ...cond, value: orStructuredConditionMap.get(key) }\n }\n return cond\n })\n\n q = q.or(rebuildOrString(conditions))\n }\n }\n\n // Apply raw filters\n for (let i = 0; i < this.rawFilters.length; i++) {\n const rf = this.rawFilters[i]\n const value = rawValueMap.has(i) ? rawValueMap.get(i) : rf.value\n q = q.filter(rf.column, rf.operator, value)\n }\n\n return q\n }\n\n // ---------------------------------------------------------------------------\n // Step 5: Decrypt results\n // ---------------------------------------------------------------------------\n\n private async decryptResults(\n result: RawSupabaseResult,\n ): Promise<EncryptedSupabaseResponse<T[]>> {\n // If there's an error from Supabase, pass it through\n if (result.error) {\n return {\n data: null,\n error: {\n message: result.error.message,\n details: result.error.details,\n hint: result.error.hint,\n code: result.error.code,\n },\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // No data to decrypt\n if (result.data === null || result.data === undefined) {\n return {\n data: null,\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Determine if we need to decrypt\n const hasSelect = this.selectColumns !== null\n const hasMutationWithReturning = this.mutation !== null && hasSelect\n\n if (!hasSelect && !hasMutationWithReturning) {\n // No select means no data to decrypt (e.g., insert without .select())\n return {\n data: result.data as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Decrypt based on result mode\n if (this.resultMode === 'single' || this.resultMode === 'maybeSingle') {\n if (result.data === null) {\n return {\n data: null,\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Single result — decrypt one model\n const baseDecryptOp = this.encryptionClient.decryptModel(\n result.data as Record<string, unknown>,\n )\n const decryptOp = this.lockContext\n ? baseDecryptOp.withLockContext(this.lockContext)\n : baseDecryptOp\n if (this.auditConfig) decryptOp.audit(this.auditConfig)\n\n const decrypted = await decryptOp\n if (decrypted.failure) {\n logger.error(\n `Supabase: failed to decrypt model for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to decrypt model: ${decrypted.failure.message}`,\n decrypted.failure,\n )\n }\n\n return {\n data: decrypted.data as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Array result — bulk decrypt\n const dataArray = result.data as Record<string, unknown>[]\n if (dataArray.length === 0) {\n return {\n data: [] as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n const baseBulkDecryptOp = this.encryptionClient.bulkDecryptModels(dataArray)\n const bulkDecryptOp = this.lockContext\n ? baseBulkDecryptOp.withLockContext(this.lockContext)\n : baseBulkDecryptOp\n if (this.auditConfig) bulkDecryptOp.audit(this.auditConfig)\n\n const decrypted = await bulkDecryptOp\n if (decrypted.failure) {\n logger.error(\n `Supabase: failed to decrypt models for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to decrypt models: ${decrypted.failure.message}`,\n decrypted.failure,\n )\n }\n\n return {\n data: decrypted.data as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n private getColumnMap(): Record<string, EncryptedColumn> {\n const map: Record<string, EncryptedColumn> = {}\n const schema = this.schema as unknown as Record<string, unknown>\n\n for (const colName of this.encryptedColumnNames) {\n const col = schema[colName]\n if (col instanceof EncryptedColumn) {\n map[colName] = col\n }\n }\n\n return map\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype TermMapping =\n | { source: 'filter'; filterIndex: number; inIndex?: number }\n | { source: 'match'; matchIndex: number; column: string }\n | { source: 'not'; notIndex: number }\n | { source: 'raw'; rawIndex: number }\n | { source: 'or-string'; orIndex: number; conditionIndex: number }\n | { source: 'or-structured'; orIndex: number; conditionIndex: number }\n\ntype EncryptedFilterState = {\n encryptedValues: unknown[]\n termMap: TermMapping[]\n}\n\ntype RawSupabaseResult = {\n data: unknown\n error: {\n message: string\n details?: string\n hint?: string\n code?: string\n } | null\n count?: number | null\n status: number\n statusText: string\n}\n\nclass EncryptionFailedError extends Error {\n public encryptionError: unknown\n\n constructor(message: string, encryptionError: unknown) {\n super(message)\n this.name = 'EncryptionFailedError'\n this.encryptionError = encryptionError\n }\n}\n","import type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport { EncryptedQueryBuilderImpl } from './query-builder'\nimport type {\n EncryptedSupabaseConfig,\n EncryptedSupabaseInstance,\n} from './types'\n\n/**\n * Create an encrypted Supabase wrapper that transparently handles encryption\n * and decryption for queries on encrypted columns.\n *\n * @param config - Configuration containing the encryption client and Supabase client.\n * @returns An object with a `from()` method that mirrors `supabase.from()` but\n * auto-encrypts mutations, adds `::jsonb` casts, encrypts filter values, and\n * decrypts results.\n *\n * @example\n * ```typescript\n * import { Encryption } from '@cipherstash/stack'\n * import { encryptedSupabase } from '@cipherstash/stack/supabase'\n * import { encryptedTable, encryptedColumn } from '@cipherstash/stack/schema'\n *\n * const users = encryptedTable('users', {\n * name: encryptedColumn('name').freeTextSearch().equality(),\n * email: encryptedColumn('email').freeTextSearch().equality(),\n * })\n *\n * const client = await Encryption({ schemas: [users] })\n * const eSupabase = encryptedSupabase({ encryptionClient: client, supabaseClient: supabase })\n *\n * // INSERT - auto-encrypts, auto-converts to PG composite\n * await eSupabase.from('users', users)\n * .insert({ name: 'John', email: 'john@example.com', age: 30 })\n *\n * // SELECT with filter - auto-casts ::jsonb, auto-encrypts search term, auto-decrypts\n * const { data } = await eSupabase.from('users', users)\n * .select('id, email, name')\n * .eq('email', 'john@example.com')\n * ```\n */\nexport function encryptedSupabase(\n config: EncryptedSupabaseConfig,\n): EncryptedSupabaseInstance {\n const { encryptionClient, supabaseClient } = config\n\n return {\n from<T extends Record<string, unknown> = Record<string, unknown>>(\n tableName: string,\n schema: EncryptedTable<EncryptedTableColumn>,\n ) {\n return new EncryptedQueryBuilderImpl<T>(\n tableName,\n schema,\n encryptionClient,\n supabaseClient,\n )\n },\n }\n}\n\nexport type {\n EncryptedSupabaseConfig,\n EncryptedSupabaseInstance,\n EncryptedSupabaseResponse,\n EncryptedSupabaseError,\n EncryptedQueryBuilder,\n PendingOrCondition,\n SupabaseClientLike,\n} from './types'\n"],"mappings":"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","names":["baseOp","op","result","decrypted"]}
|
|
1
|
+
{"version":3,"sources":["../../src/supabase/helpers.ts","../../src/supabase/query-builder.ts","../../src/supabase/index.ts"],"sourcesContent":["import type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport type { QueryTypeName } from '@/types'\nimport type { FilterOp, PendingOrCondition } from './types'\n\n/**\n * Get the names of all encrypted columns defined in a table schema.\n */\nexport function getEncryptedColumnNames(\n schema: EncryptedTable<EncryptedTableColumn>,\n): string[] {\n const built = schema.build()\n return Object.keys(built.columns)\n}\n\n/**\n * Check whether a column name refers to an encrypted column in the schema.\n */\nexport function isEncryptedColumn(\n columnName: string,\n encryptedColumnNames: string[],\n): boolean {\n return encryptedColumnNames.includes(columnName)\n}\n\n/**\n * Parse a Supabase select string and add `::jsonb` casts to encrypted columns.\n *\n * Input: `'id, email, name'`\n * Output: `'id, email::jsonb, name::jsonb'` (if email and name are encrypted)\n *\n * Handles whitespace, already-cast columns, and embedded functions.\n */\nexport function addJsonbCasts(\n columns: string,\n encryptedColumnNames: string[],\n): string {\n return columns\n .split(',')\n .map((col) => {\n const trimmed = col.trim()\n\n // Skip empty segments\n if (!trimmed) return col\n\n // If it already has a cast (e.g. `email::jsonb`), skip\n if (trimmed.includes('::')) return col\n\n // If it contains parens (function call) or dots (foreign table), skip\n if (trimmed.includes('(') || trimmed.includes('.')) return col\n\n // Check if the column name (possibly with alias) is encrypted\n // Handle `column_name` or `column_name as alias`\n const parts = trimmed.split(/\\s+/)\n const colName = parts[0]\n\n if (isEncryptedColumn(colName, encryptedColumnNames)) {\n // Preserve original whitespace before the column\n const leadingWhitespace = col.match(/^(\\s*)/)?.[1] ?? ''\n if (parts.length > 1) {\n // Has alias: `email as e` -> `email::jsonb as e`\n return `${leadingWhitespace}${colName}::jsonb ${parts.slice(1).join(' ')}`\n }\n return `${leadingWhitespace}${colName}::jsonb`\n }\n\n return col\n })\n .join(',')\n}\n\n/**\n * Map a Supabase filter operation to a CipherStash query type.\n */\nexport function mapFilterOpToQueryType(op: FilterOp): QueryTypeName {\n switch (op) {\n case 'eq':\n case 'neq':\n case 'in':\n case 'is':\n return 'equality'\n case 'like':\n case 'ilike':\n return 'freeTextSearch'\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte':\n return 'orderAndRange'\n default:\n return 'equality'\n }\n}\n\n/**\n * Parse a Supabase `.or()` filter string into structured conditions.\n *\n * Input: `'email.eq.john@example.com,name.ilike.%john%'`\n * Output: `[{ column: 'email', op: 'eq', value: 'john@example.com' }, { column: 'name', op: 'ilike', value: '%john%' }]`\n */\nexport function parseOrString(orString: string): PendingOrCondition[] {\n const conditions: PendingOrCondition[] = []\n // Split on commas that are not inside parentheses (nested or/and)\n const parts = splitOrString(orString)\n\n for (const part of parts) {\n const trimmed = part.trim()\n if (!trimmed) continue\n\n // Format: column.op.value\n const firstDot = trimmed.indexOf('.')\n if (firstDot === -1) continue\n\n const column = trimmed.slice(0, firstDot)\n const rest = trimmed.slice(firstDot + 1)\n\n const secondDot = rest.indexOf('.')\n if (secondDot === -1) continue\n\n const op = rest.slice(0, secondDot) as FilterOp\n const value = rest.slice(secondDot + 1)\n\n // Handle special value formats\n const parsedValue = parseOrValue(value)\n\n conditions.push({ column, op, value: parsedValue })\n }\n\n return conditions\n}\n\n/**\n * Rebuild an `.or()` string from structured conditions.\n */\nexport function rebuildOrString(conditions: PendingOrCondition[]): string {\n return conditions\n .map((c) => {\n const value = formatOrValue(c.value)\n return `${c.column}.${c.op}.${value}`\n })\n .join(',')\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction splitOrString(input: string): string[] {\n const parts: string[] = []\n let current = ''\n let depth = 0\n let inQuotes = false\n\n for (const char of input) {\n if (char === '\"' && depth === 0) {\n inQuotes = !inQuotes\n current += char\n } else if (char === '(' && !inQuotes) {\n depth++\n current += char\n } else if (char === ')' && !inQuotes) {\n depth--\n current += char\n } else if (char === ',' && depth === 0 && !inQuotes) {\n parts.push(current)\n current = ''\n } else {\n current += char\n }\n }\n\n if (current) {\n parts.push(current)\n }\n\n return parts\n}\n\nfunction parseOrValue(value: string): unknown {\n // Handle double-quoted values (PostgREST quoting for reserved characters)\n if (value.startsWith('\"') && value.endsWith('\"')) {\n return value.slice(1, -1)\n }\n\n // Handle parenthesized lists: (val1,val2,val3)\n if (value.startsWith('(') && value.endsWith(')')) {\n return value\n .slice(1, -1)\n .split(',')\n .map((v) => v.trim())\n }\n\n // Handle booleans\n if (value === 'true') return true\n if (value === 'false') return false\n\n // Handle null\n if (value === 'null') return null\n\n return value\n}\n\n/**\n * PostgREST reserved characters that require double-quoting in filter values.\n * See: https://docs.postgrest.org/en/latest/references/api/tables_views.html\n */\nconst POSTGREST_RESERVED = /[,().]/\n\nfunction formatOrValue(value: unknown): string {\n if (Array.isArray(value)) {\n return `(${value.join(',')})`\n }\n if (value === null) return 'null'\n if (value === true) return 'true'\n if (value === false) return 'false'\n\n const str = String(value)\n\n // Wrap in double quotes if the value contains reserved characters.\n // This is required for encrypted values (JSON with commas, braces, etc.)\n // and is safe for all string values per PostgREST spec.\n if (POSTGREST_RESERVED.test(str)) {\n return `\"${str}\"`\n }\n\n return str\n}\n","import type { EncryptionClient } from '@/encryption'\nimport {\n bulkModelsToEncryptedPgComposites,\n modelToEncryptedPgComposites,\n} from '@/encryption/helpers'\nimport type { AuditConfig } from '@/encryption/operations/base-operation'\nimport type { LockContext } from '@/identity'\nimport type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport { EncryptedColumn } from '@/schema'\nimport type { ScalarQueryTerm } from '@/types'\nimport { logger } from '@/utils/logger'\nimport type { JsPlaintext } from '@cipherstash/protect-ffi'\nimport {\n addJsonbCasts,\n getEncryptedColumnNames,\n isEncryptedColumn,\n mapFilterOpToQueryType,\n parseOrString,\n rebuildOrString,\n} from './helpers'\nimport type {\n EncryptedSupabaseError,\n EncryptedSupabaseResponse,\n FilterOp,\n MutationOp,\n PendingFilter,\n PendingMatchFilter,\n PendingNotFilter,\n PendingOrCondition,\n PendingOrFilter,\n PendingRawFilter,\n ResultMode,\n SupabaseClientLike,\n SupabaseQueryBuilder,\n TransformOp,\n} from './types'\n\n/**\n * A deferred query builder that wraps Supabase's query builder to automatically\n * handle encryption and decryption of data.\n *\n * All chained operations are recorded synchronously. When the builder is awaited,\n * it encrypts mutation data, adds `::jsonb` casts, batch-encrypts filter values,\n * executes the real Supabase query, and decrypts results.\n */\nexport class EncryptedQueryBuilderImpl<\n T extends Record<string, unknown> = Record<string, unknown>,\n> {\n private tableName: string\n private schema: EncryptedTable<EncryptedTableColumn>\n private encryptionClient: EncryptionClient\n private supabaseClient: SupabaseClientLike\n private encryptedColumnNames: string[]\n\n // Recorded operations\n private mutation: MutationOp | null = null\n private selectColumns: string | null = null\n private selectOptions:\n | { head?: boolean; count?: 'exact' | 'planned' | 'estimated' }\n | undefined = undefined\n private filters: PendingFilter[] = []\n private orFilters: PendingOrFilter[] = []\n private matchFilters: PendingMatchFilter[] = []\n private notFilters: PendingNotFilter[] = []\n private rawFilters: PendingRawFilter[] = []\n private transforms: TransformOp[] = []\n private resultMode: ResultMode = 'array'\n private shouldThrowOnError = false\n\n // Encryption-specific state\n private lockContext: LockContext | null = null\n private auditConfig: AuditConfig | null = null\n\n constructor(\n tableName: string,\n schema: EncryptedTable<EncryptedTableColumn>,\n encryptionClient: EncryptionClient,\n supabaseClient: SupabaseClientLike,\n ) {\n this.tableName = tableName\n this.schema = schema\n this.encryptionClient = encryptionClient\n this.supabaseClient = supabaseClient\n this.encryptedColumnNames = getEncryptedColumnNames(schema)\n }\n\n // ---------------------------------------------------------------------------\n // Mutation methods\n // ---------------------------------------------------------------------------\n\n select(\n columns: string,\n options?: { head?: boolean; count?: 'exact' | 'planned' | 'estimated' },\n ): this {\n if (columns === '*') {\n throw new Error(\n \"encryptedSupabase does not support select('*'). Please list columns explicitly so that encrypted columns can be cast with ::jsonb.\",\n )\n }\n this.selectColumns = columns\n this.selectOptions = options\n return this\n }\n\n insert(\n data: Partial<T> | Partial<T>[],\n options?: {\n count?: 'exact' | 'planned' | 'estimated'\n defaultToNull?: boolean\n onConflict?: string\n },\n ): this {\n this.mutation = {\n kind: 'insert',\n data: data as Record<string, unknown> | Record<string, unknown>[],\n options,\n }\n return this\n }\n\n update(\n data: Partial<T>,\n options?: { count?: 'exact' | 'planned' | 'estimated' },\n ): this {\n this.mutation = {\n kind: 'update',\n data: data as Record<string, unknown>,\n options,\n }\n return this\n }\n\n upsert(\n data: Partial<T> | Partial<T>[],\n options?: {\n count?: 'exact' | 'planned' | 'estimated'\n onConflict?: string\n ignoreDuplicates?: boolean\n defaultToNull?: boolean\n },\n ): this {\n this.mutation = {\n kind: 'upsert',\n data: data as Record<string, unknown> | Record<string, unknown>[],\n options,\n }\n return this\n }\n\n delete(options?: { count?: 'exact' | 'planned' | 'estimated' }): this {\n this.mutation = { kind: 'delete', options }\n return this\n }\n\n // ---------------------------------------------------------------------------\n // Filter methods\n // ---------------------------------------------------------------------------\n\n eq(column: string, value: unknown): this {\n this.filters.push({ op: 'eq', column, value })\n return this\n }\n\n neq(column: string, value: unknown): this {\n this.filters.push({ op: 'neq', column, value })\n return this\n }\n\n gt(column: string, value: unknown): this {\n this.filters.push({ op: 'gt', column, value })\n return this\n }\n\n gte(column: string, value: unknown): this {\n this.filters.push({ op: 'gte', column, value })\n return this\n }\n\n lt(column: string, value: unknown): this {\n this.filters.push({ op: 'lt', column, value })\n return this\n }\n\n lte(column: string, value: unknown): this {\n this.filters.push({ op: 'lte', column, value })\n return this\n }\n\n like(column: string, pattern: string): this {\n this.filters.push({ op: 'like', column, value: pattern })\n return this\n }\n\n ilike(column: string, pattern: string): this {\n this.filters.push({ op: 'ilike', column, value: pattern })\n return this\n }\n\n is(column: string, value: null | boolean): this {\n this.filters.push({ op: 'is', column, value })\n return this\n }\n\n in(column: string, values: unknown[]): this {\n this.filters.push({ op: 'in', column, value: values })\n return this\n }\n\n filter(column: string, operator: string, value: unknown): this {\n this.rawFilters.push({ column, operator, value })\n return this\n }\n\n not(column: string, operator: string, value: unknown): this {\n this.notFilters.push({ column, op: operator as FilterOp, value })\n return this\n }\n\n or(\n filtersOrConditions: string | PendingOrCondition[],\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n if (typeof filtersOrConditions === 'string') {\n this.orFilters.push({\n kind: 'string',\n value: filtersOrConditions,\n referencedTable: options?.referencedTable ?? options?.foreignTable,\n })\n } else {\n this.orFilters.push({\n kind: 'structured',\n conditions: filtersOrConditions,\n })\n }\n return this\n }\n\n match(query: Record<string, unknown>): this {\n this.matchFilters.push({ query })\n return this\n }\n\n // ---------------------------------------------------------------------------\n // Transform methods (passthrough)\n // ---------------------------------------------------------------------------\n\n order(\n column: string,\n options?: {\n ascending?: boolean\n nullsFirst?: boolean\n referencedTable?: string\n foreignTable?: string\n },\n ): this {\n this.transforms.push({ kind: 'order', column, options })\n return this\n }\n\n limit(\n count: number,\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n this.transforms.push({ kind: 'limit', count, options })\n return this\n }\n\n range(\n from: number,\n to: number,\n options?: { referencedTable?: string; foreignTable?: string },\n ): this {\n this.transforms.push({ kind: 'range', from, to, options })\n return this\n }\n\n single(): this {\n this.resultMode = 'single'\n this.transforms.push({ kind: 'single' })\n return this\n }\n\n maybeSingle(): this {\n this.resultMode = 'maybeSingle'\n this.transforms.push({ kind: 'maybeSingle' })\n return this\n }\n\n csv(): this {\n this.transforms.push({ kind: 'csv' })\n return this\n }\n\n abortSignal(signal: AbortSignal): this {\n this.transforms.push({ kind: 'abortSignal', signal })\n return this\n }\n\n throwOnError(): this {\n this.shouldThrowOnError = true\n this.transforms.push({ kind: 'throwOnError' })\n return this\n }\n\n returns<U extends Record<string, unknown>>(): EncryptedQueryBuilderImpl<U> {\n // Type-level cast only; builder state is preserved\n return this as unknown as EncryptedQueryBuilderImpl<U>\n }\n\n // ---------------------------------------------------------------------------\n // Encryption-specific methods\n // ---------------------------------------------------------------------------\n\n withLockContext(lockContext: LockContext): this {\n this.lockContext = lockContext\n return this\n }\n\n audit(config: AuditConfig): this {\n this.auditConfig = config\n return this\n }\n\n // ---------------------------------------------------------------------------\n // PromiseLike implementation (deferred execution)\n // ---------------------------------------------------------------------------\n\n then<TResult1 = EncryptedSupabaseResponse<T[]>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: EncryptedSupabaseResponse<T[]>,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected)\n }\n\n // ---------------------------------------------------------------------------\n // Core execution\n // ---------------------------------------------------------------------------\n\n private async execute(): Promise<EncryptedSupabaseResponse<T[]>> {\n try {\n logger.debug(`Supabase encrypted query on table \"${this.tableName}\".`)\n\n // 1. Encrypt mutation data\n const encryptedMutation = await this.encryptMutationData()\n\n // 2. Build select string with ::jsonb casts\n const selectString = this.buildSelectString()\n\n // 3. Batch-encrypt filter values\n const encryptedFilters = await this.encryptFilterValues()\n\n // 4. Build and execute real Supabase query\n const result = await this.buildAndExecuteQuery(\n encryptedMutation,\n selectString,\n encryptedFilters,\n )\n\n // 5. Decrypt results\n return await this.decryptResults(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.error(\n `Supabase encrypted query failed on table \"${this.tableName}\": ${message}`,\n )\n\n const error: EncryptedSupabaseError = {\n message,\n encryptionError: undefined,\n }\n\n if (this.shouldThrowOnError) {\n throw err\n }\n\n return {\n data: null,\n error,\n count: null,\n status: 500,\n statusText: 'Encryption Error',\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Step 1: Encrypt mutation data\n // ---------------------------------------------------------------------------\n\n private async encryptMutationData(): Promise<\n Record<string, unknown> | Record<string, unknown>[] | null\n > {\n if (!this.mutation) return null\n\n if (this.mutation.kind === 'delete') return null\n\n const data = this.mutation.data\n\n if (Array.isArray(data)) {\n // Bulk encrypt\n const baseOp = this.encryptionClient.bulkEncryptModels(data, this.schema)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt models for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt models: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return bulkModelsToEncryptedPgComposites(result.data)\n }\n\n // Single model\n const baseOp = this.encryptionClient.encryptModel(data, this.schema)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt model for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt model: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return modelToEncryptedPgComposites(result.data)\n }\n\n // ---------------------------------------------------------------------------\n // Step 2: Build select string with casts\n // ---------------------------------------------------------------------------\n\n private buildSelectString(): string | null {\n if (this.selectColumns === null) return null\n return addJsonbCasts(this.selectColumns, this.encryptedColumnNames)\n }\n\n // ---------------------------------------------------------------------------\n // Step 3: Encrypt filter values\n // ---------------------------------------------------------------------------\n\n private async encryptFilterValues(): Promise<EncryptedFilterState> {\n // Collect all terms that need encryption\n const terms: ScalarQueryTerm[] = []\n const termMap: TermMapping[] = []\n\n const tableColumns = this.getColumnMap()\n\n // Regular filters\n for (let i = 0; i < this.filters.length; i++) {\n const f = this.filters[i]\n if (!isEncryptedColumn(f.column, this.encryptedColumnNames)) continue\n\n const column = tableColumns[f.column]\n if (!column) continue\n\n if (f.op === 'in' && Array.isArray(f.value)) {\n // For `in` filters, encrypt each value separately\n for (let j = 0; j < f.value.length; j++) {\n terms.push({\n value: f.value[j] as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(f.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'filter', filterIndex: i, inIndex: j })\n }\n } else if (f.op === 'is') {\n // `is` is used for null/boolean checks — don't encrypt\n continue\n } else {\n terms.push({\n value: f.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(f.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'filter', filterIndex: i })\n }\n }\n\n // Match filters\n for (let i = 0; i < this.matchFilters.length; i++) {\n const mf = this.matchFilters[i]\n for (const [colName, value] of Object.entries(mf.query)) {\n if (!isEncryptedColumn(colName, this.encryptedColumnNames)) continue\n const column = tableColumns[colName]\n if (!column) continue\n\n terms.push({\n value: value as JsPlaintext,\n column,\n table: this.schema,\n queryType: 'equality',\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'match', matchIndex: i, column: colName })\n }\n }\n\n // Not filters\n for (let i = 0; i < this.notFilters.length; i++) {\n const nf = this.notFilters[i]\n if (!isEncryptedColumn(nf.column, this.encryptedColumnNames)) continue\n const column = tableColumns[nf.column]\n if (!column) continue\n\n terms.push({\n value: nf.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(nf.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'not', notIndex: i })\n }\n\n // Or filters (string form parsed into conditions)\n for (let i = 0; i < this.orFilters.length; i++) {\n const of_ = this.orFilters[i]\n if (of_.kind === 'string') {\n const parsed = parseOrString(of_.value)\n for (let j = 0; j < parsed.length; j++) {\n const cond = parsed[j]\n if (!isEncryptedColumn(cond.column, this.encryptedColumnNames))\n continue\n const column = tableColumns[cond.column]\n if (!column) continue\n\n terms.push({\n value: cond.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(cond.op),\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'or-string', orIndex: i, conditionIndex: j })\n }\n } else {\n for (let j = 0; j < of_.conditions.length; j++) {\n const cond = of_.conditions[j]\n if (!isEncryptedColumn(cond.column, this.encryptedColumnNames))\n continue\n const column = tableColumns[cond.column]\n if (!column) continue\n\n terms.push({\n value: cond.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: mapFilterOpToQueryType(cond.op),\n returnType: 'composite-literal',\n })\n termMap.push({\n source: 'or-structured',\n orIndex: i,\n conditionIndex: j,\n })\n }\n }\n }\n\n // Raw filters\n for (let i = 0; i < this.rawFilters.length; i++) {\n const rf = this.rawFilters[i]\n if (!isEncryptedColumn(rf.column, this.encryptedColumnNames)) continue\n const column = tableColumns[rf.column]\n if (!column) continue\n\n terms.push({\n value: rf.value as JsPlaintext,\n column,\n table: this.schema,\n queryType: 'equality',\n returnType: 'composite-literal',\n })\n termMap.push({ source: 'raw', rawIndex: i })\n }\n\n if (terms.length === 0) {\n return { encryptedValues: [], termMap: [] }\n }\n\n // Batch encrypt all terms in one call\n const baseOp = this.encryptionClient.encryptQuery(terms)\n const op = this.lockContext\n ? baseOp.withLockContext(this.lockContext)\n : baseOp\n if (this.auditConfig) op.audit(this.auditConfig)\n\n const result = await op\n if (result.failure) {\n logger.error(\n `Supabase: failed to encrypt query terms for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to encrypt query terms: ${result.failure.message}`,\n result.failure,\n )\n }\n\n return { encryptedValues: result.data, termMap }\n }\n\n // ---------------------------------------------------------------------------\n // Step 4: Build and execute real Supabase query\n // ---------------------------------------------------------------------------\n\n private async buildAndExecuteQuery(\n encryptedMutation:\n | Record<string, unknown>\n | Record<string, unknown>[]\n | null,\n selectString: string | null,\n encryptedFilters: EncryptedFilterState,\n ): Promise<RawSupabaseResult> {\n let query: SupabaseQueryBuilder = this.supabaseClient.from(this.tableName)\n\n // Apply mutation\n if (this.mutation) {\n switch (this.mutation.kind) {\n case 'insert':\n query = query.insert(encryptedMutation!, this.mutation.options)\n break\n case 'update':\n query = query.update(encryptedMutation!, this.mutation.options)\n break\n case 'upsert':\n query = query.upsert(encryptedMutation!, this.mutation.options)\n break\n case 'delete':\n query = query.delete(this.mutation.options)\n break\n }\n }\n\n // Apply select\n if (selectString !== null) {\n query = query.select(selectString, this.selectOptions)\n } else if (!this.mutation) {\n // Default select without explicit columns - shouldn't happen but fallback\n query = query.select('*', this.selectOptions)\n }\n\n // Apply resolved filters\n query = this.applyFilters(query, encryptedFilters)\n\n // Apply transforms\n for (const t of this.transforms) {\n switch (t.kind) {\n case 'order':\n query = query.order(t.column, t.options)\n break\n case 'limit':\n query = query.limit(t.count, t.options)\n break\n case 'range':\n query = query.range(t.from, t.to, t.options)\n break\n case 'single':\n query = query.single()\n break\n case 'maybeSingle':\n query = query.maybeSingle()\n break\n case 'csv':\n query = query.csv()\n break\n case 'abortSignal':\n query = query.abortSignal(t.signal)\n break\n case 'throwOnError':\n query = query.throwOnError()\n break\n }\n }\n\n const result = (await query) as unknown as RawSupabaseResult\n return result\n }\n\n // ---------------------------------------------------------------------------\n // Apply filters with encrypted values substituted\n // ---------------------------------------------------------------------------\n\n private applyFilters(\n query: SupabaseQueryBuilder,\n encryptedFilters: EncryptedFilterState,\n ): SupabaseQueryBuilder {\n let q = query\n\n // Build lookup maps for quick access to encrypted values\n const filterValueMap = new Map<number, unknown>()\n const filterInMap = new Map<string, unknown>() // \"filterIndex:inIndex\" -> value\n const matchValueMap = new Map<string, unknown>() // \"matchIndex:column\" -> value\n const notValueMap = new Map<number, unknown>()\n const rawValueMap = new Map<number, unknown>()\n const orStringConditionMap = new Map<string, unknown>() // \"orIndex:condIndex\" -> value\n const orStructuredConditionMap = new Map<string, unknown>()\n\n for (let i = 0; i < encryptedFilters.termMap.length; i++) {\n const mapping = encryptedFilters.termMap[i]\n const encValue = encryptedFilters.encryptedValues[i]\n\n switch (mapping.source) {\n case 'filter':\n if (mapping.inIndex !== undefined) {\n filterInMap.set(\n `${mapping.filterIndex}:${mapping.inIndex}`,\n encValue,\n )\n } else {\n filterValueMap.set(mapping.filterIndex, encValue)\n }\n break\n case 'match':\n matchValueMap.set(`${mapping.matchIndex}:${mapping.column}`, encValue)\n break\n case 'not':\n notValueMap.set(mapping.notIndex, encValue)\n break\n case 'raw':\n rawValueMap.set(mapping.rawIndex, encValue)\n break\n case 'or-string':\n orStringConditionMap.set(\n `${mapping.orIndex}:${mapping.conditionIndex}`,\n encValue,\n )\n break\n case 'or-structured':\n orStructuredConditionMap.set(\n `${mapping.orIndex}:${mapping.conditionIndex}`,\n encValue,\n )\n break\n }\n }\n\n // Apply regular filters\n for (let i = 0; i < this.filters.length; i++) {\n const f = this.filters[i]\n let value = f.value\n\n if (filterValueMap.has(i)) {\n value = filterValueMap.get(i)\n } else if (f.op === 'in' && Array.isArray(f.value)) {\n // Reconstruct array with encrypted values substituted\n value = f.value.map((v, j) => {\n const key = `${i}:${j}`\n return filterInMap.has(key) ? filterInMap.get(key) : v\n })\n }\n\n switch (f.op) {\n case 'eq':\n q = q.eq(f.column, value)\n break\n case 'neq':\n q = q.neq(f.column, value)\n break\n case 'gt':\n q = q.gt(f.column, value)\n break\n case 'gte':\n q = q.gte(f.column, value)\n break\n case 'lt':\n q = q.lt(f.column, value)\n break\n case 'lte':\n q = q.lte(f.column, value)\n break\n case 'like':\n q = q.like(f.column, value as string)\n break\n case 'ilike':\n q = q.ilike(f.column, value as string)\n break\n case 'is':\n q = q.is(f.column, value)\n break\n case 'in':\n q = q.in(f.column, value as unknown[])\n break\n }\n }\n\n // Apply match filters\n for (let i = 0; i < this.matchFilters.length; i++) {\n const mf = this.matchFilters[i]\n const resolvedQuery: Record<string, unknown> = {}\n\n for (const [colName, originalValue] of Object.entries(mf.query)) {\n const key = `${i}:${colName}`\n resolvedQuery[colName] = matchValueMap.has(key)\n ? matchValueMap.get(key)\n : originalValue\n }\n\n q = q.match(resolvedQuery)\n }\n\n // Apply not filters\n for (let i = 0; i < this.notFilters.length; i++) {\n const nf = this.notFilters[i]\n const value = notValueMap.has(i) ? notValueMap.get(i) : nf.value\n q = q.not(nf.column, nf.op, value)\n }\n\n // Apply or filters\n for (let i = 0; i < this.orFilters.length; i++) {\n const of_ = this.orFilters[i]\n\n if (of_.kind === 'string') {\n const parsed = parseOrString(of_.value)\n let hasEncrypted = false\n\n for (let j = 0; j < parsed.length; j++) {\n const key = `${i}:${j}`\n if (orStringConditionMap.has(key)) {\n parsed[j] = { ...parsed[j], value: orStringConditionMap.get(key) }\n hasEncrypted = true\n }\n }\n\n if (hasEncrypted) {\n q = q.or(rebuildOrString(parsed), {\n referencedTable: of_.referencedTable,\n })\n } else {\n q = q.or(of_.value, { referencedTable: of_.referencedTable })\n }\n } else {\n // Structured: convert to string\n const conditions = of_.conditions.map((cond, j) => {\n const key = `${i}:${j}`\n if (orStructuredConditionMap.has(key)) {\n return { ...cond, value: orStructuredConditionMap.get(key) }\n }\n return cond\n })\n\n q = q.or(rebuildOrString(conditions))\n }\n }\n\n // Apply raw filters\n for (let i = 0; i < this.rawFilters.length; i++) {\n const rf = this.rawFilters[i]\n const value = rawValueMap.has(i) ? rawValueMap.get(i) : rf.value\n q = q.filter(rf.column, rf.operator, value)\n }\n\n return q\n }\n\n // ---------------------------------------------------------------------------\n // Step 5: Decrypt results\n // ---------------------------------------------------------------------------\n\n private async decryptResults(\n result: RawSupabaseResult,\n ): Promise<EncryptedSupabaseResponse<T[]>> {\n // If there's an error from Supabase, pass it through\n if (result.error) {\n return {\n data: null,\n error: {\n message: result.error.message,\n details: result.error.details,\n hint: result.error.hint,\n code: result.error.code,\n },\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // No data to decrypt\n if (result.data === null || result.data === undefined) {\n return {\n data: null,\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Determine if we need to decrypt\n const hasSelect = this.selectColumns !== null\n const hasMutationWithReturning = this.mutation !== null && hasSelect\n\n if (!hasSelect && !hasMutationWithReturning) {\n // No select means no data to decrypt (e.g., insert without .select())\n return {\n data: result.data as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Decrypt based on result mode\n if (this.resultMode === 'single' || this.resultMode === 'maybeSingle') {\n if (result.data === null) {\n return {\n data: null,\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Single result — decrypt one model\n const baseDecryptOp = this.encryptionClient.decryptModel(\n result.data as Record<string, unknown>,\n )\n const decryptOp = this.lockContext\n ? baseDecryptOp.withLockContext(this.lockContext)\n : baseDecryptOp\n if (this.auditConfig) decryptOp.audit(this.auditConfig)\n\n const decrypted = await decryptOp\n if (decrypted.failure) {\n logger.error(\n `Supabase: failed to decrypt model for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to decrypt model: ${decrypted.failure.message}`,\n decrypted.failure,\n )\n }\n\n return {\n data: decrypted.data as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // Array result — bulk decrypt\n const dataArray = result.data as Record<string, unknown>[]\n if (dataArray.length === 0) {\n return {\n data: [] as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n const baseBulkDecryptOp = this.encryptionClient.bulkDecryptModels(dataArray)\n const bulkDecryptOp = this.lockContext\n ? baseBulkDecryptOp.withLockContext(this.lockContext)\n : baseBulkDecryptOp\n if (this.auditConfig) bulkDecryptOp.audit(this.auditConfig)\n\n const decrypted = await bulkDecryptOp\n if (decrypted.failure) {\n logger.error(\n `Supabase: failed to decrypt models for table \"${this.tableName}\"`,\n )\n\n throw new EncryptionFailedError(\n `Failed to decrypt models: ${decrypted.failure.message}`,\n decrypted.failure,\n )\n }\n\n return {\n data: decrypted.data as unknown as T[],\n error: null,\n count: result.count ?? null,\n status: result.status,\n statusText: result.statusText,\n }\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n private getColumnMap(): Record<string, EncryptedColumn> {\n const map: Record<string, EncryptedColumn> = {}\n const schema = this.schema as unknown as Record<string, unknown>\n\n for (const colName of this.encryptedColumnNames) {\n const col = schema[colName]\n if (col instanceof EncryptedColumn) {\n map[colName] = col\n }\n }\n\n return map\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype TermMapping =\n | { source: 'filter'; filterIndex: number; inIndex?: number }\n | { source: 'match'; matchIndex: number; column: string }\n | { source: 'not'; notIndex: number }\n | { source: 'raw'; rawIndex: number }\n | { source: 'or-string'; orIndex: number; conditionIndex: number }\n | { source: 'or-structured'; orIndex: number; conditionIndex: number }\n\ntype EncryptedFilterState = {\n encryptedValues: unknown[]\n termMap: TermMapping[]\n}\n\ntype RawSupabaseResult = {\n data: unknown\n error: {\n message: string\n details?: string\n hint?: string\n code?: string\n } | null\n count?: number | null\n status: number\n statusText: string\n}\n\nclass EncryptionFailedError extends Error {\n public encryptionError: unknown\n\n constructor(message: string, encryptionError: unknown) {\n super(message)\n this.name = 'EncryptionFailedError'\n this.encryptionError = encryptionError\n }\n}\n","import type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport { EncryptedQueryBuilderImpl } from './query-builder'\nimport type {\n EncryptedSupabaseConfig,\n EncryptedSupabaseInstance,\n} from './types'\n\n/**\n * Create an encrypted Supabase wrapper that transparently handles encryption\n * and decryption for queries on encrypted columns.\n *\n * @param config - Configuration containing the encryption client and Supabase client.\n * @returns An object with a `from()` method that mirrors `supabase.from()` but\n * auto-encrypts mutations, adds `::jsonb` casts, encrypts filter values, and\n * decrypts results.\n *\n * @example\n * ```typescript\n * import { Encryption } from '@cipherstash/stack'\n * import { encryptedSupabase } from '@cipherstash/stack/supabase'\n * import { encryptedTable, encryptedColumn } from '@cipherstash/stack/schema'\n *\n * const users = encryptedTable('users', {\n * name: encryptedColumn('name').freeTextSearch().equality(),\n * email: encryptedColumn('email').freeTextSearch().equality(),\n * })\n *\n * const client = await Encryption({ schemas: [users] })\n * const eSupabase = encryptedSupabase({ encryptionClient: client, supabaseClient: supabase })\n *\n * // INSERT - auto-encrypts, auto-converts to PG composite\n * await eSupabase.from('users', users)\n * .insert({ name: 'John', email: 'john@example.com', age: 30 })\n *\n * // SELECT with filter - auto-casts ::jsonb, auto-encrypts search term, auto-decrypts\n * const { data } = await eSupabase.from('users', users)\n * .select('id, email, name')\n * .eq('email', 'john@example.com')\n * ```\n */\nexport function encryptedSupabase(\n config: EncryptedSupabaseConfig,\n): EncryptedSupabaseInstance {\n const { encryptionClient, supabaseClient } = config\n\n return {\n from<T extends Record<string, unknown> = Record<string, unknown>>(\n tableName: string,\n schema: EncryptedTable<EncryptedTableColumn>,\n ) {\n return new EncryptedQueryBuilderImpl<T>(\n tableName,\n schema,\n encryptionClient,\n supabaseClient,\n )\n },\n }\n}\n\nexport type {\n EncryptedSupabaseConfig,\n EncryptedSupabaseInstance,\n EncryptedSupabaseResponse,\n EncryptedSupabaseError,\n EncryptedQueryBuilder,\n PendingOrCondition,\n SupabaseClientLike,\n} from './types'\n"],"mappings":"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","names":["baseOp","op","result","decrypted"]}
|
|
@@ -191,7 +191,22 @@ type ScalarQueryTerm = QueryTermBase & {
|
|
|
191
191
|
*
|
|
192
192
|
* @internal
|
|
193
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* EQL cast types — the PostgreSQL-aligned types that EQL actually accepts.
|
|
196
|
+
* These are stored in the `cast_as` field of the EncryptConfig.
|
|
197
|
+
*/
|
|
198
|
+
declare const eqlCastAsEnum: z.ZodDefault<z.ZodEnum<["text", "int", "small_int", "big_int", "real", "double", "boolean", "date", "jsonb"]>>;
|
|
199
|
+
/**
|
|
200
|
+
* SDK-facing data types — developer-friendly aliases accepted by `dataType()`.
|
|
201
|
+
*/
|
|
194
202
|
declare const castAsEnum: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "number", "string", "json", "text"]>>;
|
|
203
|
+
/**
|
|
204
|
+
* Map SDK-facing data types to EQL `cast_as` values.
|
|
205
|
+
*
|
|
206
|
+
* The SDK accepts developer-friendly types like `'string'` and `'number'`,
|
|
207
|
+
* but EQL expects PostgreSQL-aligned types like `'text'` and `'double'`.
|
|
208
|
+
*/
|
|
209
|
+
declare function toEqlCastAs(value: CastAs): EqlCastAs;
|
|
195
210
|
declare const tokenFilterSchema: z.ZodObject<{
|
|
196
211
|
kind: z.ZodLiteral<"downcase">;
|
|
197
212
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -410,7 +425,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
410
425
|
} | undefined;
|
|
411
426
|
}>>;
|
|
412
427
|
}, "strip", z.ZodTypeAny, {
|
|
413
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
428
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
414
429
|
indexes: {
|
|
415
430
|
match?: {
|
|
416
431
|
token_filters?: {
|
|
@@ -437,7 +452,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
437
452
|
} | undefined;
|
|
438
453
|
};
|
|
439
454
|
}, {
|
|
440
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
455
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
441
456
|
indexes?: {
|
|
442
457
|
match?: {
|
|
443
458
|
token_filters?: {
|
|
@@ -599,7 +614,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
599
614
|
} | undefined;
|
|
600
615
|
}>>;
|
|
601
616
|
}, "strip", z.ZodTypeAny, {
|
|
602
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
617
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
603
618
|
indexes: {
|
|
604
619
|
match?: {
|
|
605
620
|
token_filters?: {
|
|
@@ -626,7 +641,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
626
641
|
} | undefined;
|
|
627
642
|
};
|
|
628
643
|
}, {
|
|
629
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
644
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
630
645
|
indexes?: {
|
|
631
646
|
match?: {
|
|
632
647
|
token_filters?: {
|
|
@@ -656,7 +671,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
656
671
|
}, "strip", z.ZodTypeAny, {
|
|
657
672
|
v: number;
|
|
658
673
|
tables: Record<string, Record<string, {
|
|
659
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
674
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
660
675
|
indexes: {
|
|
661
676
|
match?: {
|
|
662
677
|
token_filters?: {
|
|
@@ -686,7 +701,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
686
701
|
}, {
|
|
687
702
|
v: number;
|
|
688
703
|
tables?: Record<string, Record<string, {
|
|
689
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
704
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
690
705
|
indexes?: {
|
|
691
706
|
match?: {
|
|
692
707
|
token_filters?: {
|
|
@@ -721,6 +736,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
721
736
|
* @see {@link castAsEnum} for possible values.
|
|
722
737
|
*/
|
|
723
738
|
type CastAs = z.infer<typeof castAsEnum>;
|
|
739
|
+
type EqlCastAs = z.infer<typeof eqlCastAsEnum>;
|
|
724
740
|
type TokenFilter = z.infer<typeof tokenFilterSchema>;
|
|
725
741
|
type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>;
|
|
726
742
|
type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>;
|
|
@@ -769,7 +785,7 @@ declare class EncryptedField {
|
|
|
769
785
|
*/
|
|
770
786
|
dataType(castAs: CastAs): this;
|
|
771
787
|
build(): {
|
|
772
|
-
cast_as: "number" | "bigint" | "boolean" | "
|
|
788
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
773
789
|
indexes: {};
|
|
774
790
|
};
|
|
775
791
|
getName(): string;
|
|
@@ -888,7 +904,7 @@ declare class EncryptedColumn {
|
|
|
888
904
|
*/
|
|
889
905
|
searchableJson(): this;
|
|
890
906
|
build(): {
|
|
891
|
-
cast_as: "number" | "bigint" | "boolean" | "
|
|
907
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
892
908
|
indexes: {
|
|
893
909
|
ore?: OreIndexOpts;
|
|
894
910
|
unique?: UniqueIndexOpts;
|
|
@@ -1065,4 +1081,4 @@ declare function encryptedField(valueName: string): EncryptedField;
|
|
|
1065
1081
|
*/
|
|
1066
1082
|
declare function buildEncryptConfig(...protectTables: Array<EncryptedTable<EncryptedTableColumn>>): EncryptConfig;
|
|
1067
1083
|
|
|
1068
|
-
export {
|
|
1084
|
+
export { eqlCastAsEnum as A, type BulkDecryptedData as B, type CastAs as C, type Decrypted as D, type Encrypted as E, toEqlCastAs as F, type ClientConfig as G, type DecryptedFields as H, type InferEncrypted as I, type DecryptionResult as J, type KeysetIdentifier as K, type EncryptedFields as L, type MatchIndexOpts as M, type EncryptedSearchTerm as N, type OreIndexOpts as O, type OtherFields as P, type QueryTypeName as Q, type SearchTerm as R, type ScalarQueryTerm as S, type TokenFilter as T, type UniqueIndexOpts as U, queryTypes as V, encryptedField as a, encryptedTable as b, EncryptedTable as c, type EncryptedTableColumn as d, encryptedColumn as e, EncryptedColumn as f, type EncryptedValue as g, type EncryptedQueryResult as h, type Client as i, type BulkDecryptPayload as j, type BulkEncryptedData as k, type BulkEncryptPayload as l, type EncryptOptions as m, EncryptedField as n, type EncryptQueryOptions as o, type EncryptedReturnType as p, type EncryptConfig as q, type EncryptedFromSchema as r, type EncryptionClientConfig as s, type InferPlaintext as t, type ColumnSchema as u, type EqlCastAs as v, type SteVecIndexOpts as w, buildEncryptConfig as x, castAsEnum as y, encryptConfigSchema as z };
|
|
@@ -191,7 +191,22 @@ type ScalarQueryTerm = QueryTermBase & {
|
|
|
191
191
|
*
|
|
192
192
|
* @internal
|
|
193
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* EQL cast types — the PostgreSQL-aligned types that EQL actually accepts.
|
|
196
|
+
* These are stored in the `cast_as` field of the EncryptConfig.
|
|
197
|
+
*/
|
|
198
|
+
declare const eqlCastAsEnum: z.ZodDefault<z.ZodEnum<["text", "int", "small_int", "big_int", "real", "double", "boolean", "date", "jsonb"]>>;
|
|
199
|
+
/**
|
|
200
|
+
* SDK-facing data types — developer-friendly aliases accepted by `dataType()`.
|
|
201
|
+
*/
|
|
194
202
|
declare const castAsEnum: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "number", "string", "json", "text"]>>;
|
|
203
|
+
/**
|
|
204
|
+
* Map SDK-facing data types to EQL `cast_as` values.
|
|
205
|
+
*
|
|
206
|
+
* The SDK accepts developer-friendly types like `'string'` and `'number'`,
|
|
207
|
+
* but EQL expects PostgreSQL-aligned types like `'text'` and `'double'`.
|
|
208
|
+
*/
|
|
209
|
+
declare function toEqlCastAs(value: CastAs): EqlCastAs;
|
|
195
210
|
declare const tokenFilterSchema: z.ZodObject<{
|
|
196
211
|
kind: z.ZodLiteral<"downcase">;
|
|
197
212
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -410,7 +425,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
410
425
|
} | undefined;
|
|
411
426
|
}>>;
|
|
412
427
|
}, "strip", z.ZodTypeAny, {
|
|
413
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
428
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
414
429
|
indexes: {
|
|
415
430
|
match?: {
|
|
416
431
|
token_filters?: {
|
|
@@ -437,7 +452,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
437
452
|
} | undefined;
|
|
438
453
|
};
|
|
439
454
|
}, {
|
|
440
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
455
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
441
456
|
indexes?: {
|
|
442
457
|
match?: {
|
|
443
458
|
token_filters?: {
|
|
@@ -599,7 +614,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
599
614
|
} | undefined;
|
|
600
615
|
}>>;
|
|
601
616
|
}, "strip", z.ZodTypeAny, {
|
|
602
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
617
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
603
618
|
indexes: {
|
|
604
619
|
match?: {
|
|
605
620
|
token_filters?: {
|
|
@@ -626,7 +641,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
626
641
|
} | undefined;
|
|
627
642
|
};
|
|
628
643
|
}, {
|
|
629
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
644
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
630
645
|
indexes?: {
|
|
631
646
|
match?: {
|
|
632
647
|
token_filters?: {
|
|
@@ -656,7 +671,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
656
671
|
}, "strip", z.ZodTypeAny, {
|
|
657
672
|
v: number;
|
|
658
673
|
tables: Record<string, Record<string, {
|
|
659
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
674
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
660
675
|
indexes: {
|
|
661
676
|
match?: {
|
|
662
677
|
token_filters?: {
|
|
@@ -686,7 +701,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
686
701
|
}, {
|
|
687
702
|
v: number;
|
|
688
703
|
tables?: Record<string, Record<string, {
|
|
689
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
704
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json" | undefined;
|
|
690
705
|
indexes?: {
|
|
691
706
|
match?: {
|
|
692
707
|
token_filters?: {
|
|
@@ -721,6 +736,7 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
721
736
|
* @see {@link castAsEnum} for possible values.
|
|
722
737
|
*/
|
|
723
738
|
type CastAs = z.infer<typeof castAsEnum>;
|
|
739
|
+
type EqlCastAs = z.infer<typeof eqlCastAsEnum>;
|
|
724
740
|
type TokenFilter = z.infer<typeof tokenFilterSchema>;
|
|
725
741
|
type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>;
|
|
726
742
|
type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>;
|
|
@@ -769,7 +785,7 @@ declare class EncryptedField {
|
|
|
769
785
|
*/
|
|
770
786
|
dataType(castAs: CastAs): this;
|
|
771
787
|
build(): {
|
|
772
|
-
cast_as: "number" | "bigint" | "boolean" | "
|
|
788
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
773
789
|
indexes: {};
|
|
774
790
|
};
|
|
775
791
|
getName(): string;
|
|
@@ -888,7 +904,7 @@ declare class EncryptedColumn {
|
|
|
888
904
|
*/
|
|
889
905
|
searchableJson(): this;
|
|
890
906
|
build(): {
|
|
891
|
-
cast_as: "number" | "bigint" | "boolean" | "
|
|
907
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "text" | "date" | "json";
|
|
892
908
|
indexes: {
|
|
893
909
|
ore?: OreIndexOpts;
|
|
894
910
|
unique?: UniqueIndexOpts;
|
|
@@ -1065,4 +1081,4 @@ declare function encryptedField(valueName: string): EncryptedField;
|
|
|
1065
1081
|
*/
|
|
1066
1082
|
declare function buildEncryptConfig(...protectTables: Array<EncryptedTable<EncryptedTableColumn>>): EncryptConfig;
|
|
1067
1083
|
|
|
1068
|
-
export {
|
|
1084
|
+
export { eqlCastAsEnum as A, type BulkDecryptedData as B, type CastAs as C, type Decrypted as D, type Encrypted as E, toEqlCastAs as F, type ClientConfig as G, type DecryptedFields as H, type InferEncrypted as I, type DecryptionResult as J, type KeysetIdentifier as K, type EncryptedFields as L, type MatchIndexOpts as M, type EncryptedSearchTerm as N, type OreIndexOpts as O, type OtherFields as P, type QueryTypeName as Q, type SearchTerm as R, type ScalarQueryTerm as S, type TokenFilter as T, type UniqueIndexOpts as U, queryTypes as V, encryptedField as a, encryptedTable as b, EncryptedTable as c, type EncryptedTableColumn as d, encryptedColumn as e, EncryptedColumn as f, type EncryptedValue as g, type EncryptedQueryResult as h, type Client as i, type BulkDecryptPayload as j, type BulkEncryptedData as k, type BulkEncryptPayload as l, type EncryptOptions as m, EncryptedField as n, type EncryptQueryOptions as o, type EncryptedReturnType as p, type EncryptConfig as q, type EncryptedFromSchema as r, type EncryptionClientConfig as s, type InferPlaintext as t, type ColumnSchema as u, type EqlCastAs as v, type SteVecIndexOpts as w, buildEncryptConfig as x, castAsEnum as y, encryptConfigSchema as z };
|
package/dist/types-public.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client,
|
|
1
|
+
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, h as EncryptedQueryResult, p as EncryptedReturnType, N as EncryptedSearchTerm, g as EncryptedValue, s as EncryptionClientConfig, K as KeysetIdentifier, P as OtherFields, Q as QueryTypeName, S as ScalarQueryTerm, R as SearchTerm, V as queryTypes } from './types-public-B5YxQhR6.cjs';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@cipherstash/protect-ffi';
|
package/dist/types-public.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client,
|
|
1
|
+
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, h as EncryptedQueryResult, p as EncryptedReturnType, N as EncryptedSearchTerm, g as EncryptedValue, s as EncryptionClientConfig, K as KeysetIdentifier, P as OtherFields, Q as QueryTypeName, S as ScalarQueryTerm, R as SearchTerm, V as queryTypes } from './types-public-B5YxQhR6.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@cipherstash/protect-ffi';
|