@cipherstash/stack 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -2
- package/dist/bin/stash.js +63 -45
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-5G4F4JJG.js → chunk-JLI27P46.js} +1 -1
- package/dist/chunk-JLI27P46.js.map +1 -0
- package/dist/{chunk-LHZ6KZIG.js → chunk-MW6D52V2.js} +42 -31
- package/dist/chunk-MW6D52V2.js.map +1 -0
- package/dist/{chunk-5DCT6YU2.js → chunk-OAPLZLR5.js} +7 -3
- package/dist/{chunk-5DCT6YU2.js.map → chunk-OAPLZLR5.js.map} +1 -1
- package/dist/{chunk-7XRPN2KX.js → chunk-TBAIVO6T.js} +26 -23
- package/dist/chunk-TBAIVO6T.js.map +1 -0
- package/dist/{client-D-ZH8SB2.d.cts → client-Bf0Xw2xo.d.cts} +19 -16
- package/dist/{client-BV9pXC-d.d.ts → client-Kfp8OsPB.d.ts} +19 -16
- package/dist/client.cjs +25 -22
- 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 +5 -5
- package/dist/drizzle/index.cjs +19 -16
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +5 -5
- package/dist/drizzle/index.d.ts +5 -5
- package/dist/drizzle/index.js +2 -2
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +10 -10
- package/dist/dynamodb/index.d.ts +10 -10
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/identity/index.cjs +6 -2
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/index.cjs +67 -49
- 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 +7 -7
- package/dist/schema/index.cjs +31 -28
- 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 +11 -11
- package/dist/secrets/index.cjs +63 -45
- 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 +4 -4
- package/dist/secrets/index.js.map +1 -1
- package/dist/supabase/index.cjs +7 -7
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +3 -3
- package/dist/supabase/index.d.ts +3 -3
- package/dist/supabase/index.js +3 -3
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-Dfg-hkuQ.d.cts → types-public-0CzBV45X.d.cts} +70 -52
- package/dist/{types-public-Dfg-hkuQ.d.ts → types-public-0CzBV45X.d.ts} +70 -52
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/dist/types-public.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5G4F4JJG.js.map +0 -1
- package/dist/chunk-7XRPN2KX.js.map +0 -1
- package/dist/chunk-LHZ6KZIG.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/supabase/index.ts","../../src/encryption/helpers/index.ts","../../src/schema/index.ts","../../src/supabase/helpers.ts","../../src/supabase/query-builder.ts"],"sourcesContent":["import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport { EncryptedQueryBuilderImpl } from './query-builder'\nimport type {\n EncryptedSupabaseConfig,\n EncryptedSupabaseInstance,\n SupabaseClientLike,\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: ProtectTable<ProtectTableColumn>,\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","import type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types'\nimport type {\n Encrypted as CipherStashEncrypted,\n KeysetIdentifier as KeysetIdentifierFfi,\n} from '@cipherstash/protect-ffi'\n\nexport type EncryptedPgComposite = {\n data: Encrypted\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite type.\n * Use this when inserting data via Supabase or similar clients.\n */\nexport function encryptedToPgComposite(obj: Encrypted): EncryptedPgComposite {\n return {\n data: obj,\n }\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite literal string.\n * Use this when querying with `.eq()` or similar equality operations in Supabase.\n *\n * @example\n * ```typescript\n * const literal = encryptedToCompositeLiteral(encrypted)\n * await supabase.from('table').select().eq('column', literal)\n * ```\n */\nexport function encryptedToCompositeLiteral(obj: CipherStashEncrypted): string {\n if (obj === null) {\n throw new Error('encryptedToCompositeLiteral: obj cannot be null')\n }\n return `(${JSON.stringify(JSON.stringify(obj))})`\n}\n\n/**\n * Helper function to transform an encrypted payload into an escaped PostgreSQL composite literal string.\n * Use this when you need the composite literal format to be escaped as a string value.\n *\n * @example\n * ```typescript\n * const escapedLiteral = encryptedToEscapedCompositeLiteral(encrypted)\n * ```\n */\nexport function encryptedToEscapedCompositeLiteral(\n obj: CipherStashEncrypted,\n): string {\n if (obj === null) {\n throw new Error('encryptedToEscapedCompositeLiteral: obj cannot be null')\n }\n return JSON.stringify(encryptedToCompositeLiteral(obj))\n}\n\n/**\n * Format an encrypted result based on the requested return type.\n *\n * - `'composite-literal'` → PostgreSQL composite literal string `(\"json\")`\n * - `'escaped-composite-literal'` → escaped variant `\"(\\\"json\\\")\"`\n * - default (`'eql'` or omitted) → raw encrypted object\n */\nexport function formatEncryptedResult(\n encrypted: CipherStashEncrypted,\n returnType?: string,\n): EncryptedQueryResult {\n if (returnType === 'composite-literal') {\n return encryptedToCompositeLiteral(encrypted)\n }\n if (returnType === 'escaped-composite-literal') {\n return encryptedToEscapedCompositeLiteral(encrypted)\n }\n return encrypted\n}\n\n/**\n * Helper function to transform a model's encrypted fields into PostgreSQL composite types\n */\nexport function modelToEncryptedPgComposites<T extends Record<string, unknown>>(\n model: T,\n): T {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (isEncryptedPayload(value)) {\n result[key] = encryptedToPgComposite(value)\n } else {\n result[key] = value\n }\n }\n\n return result as T\n}\n\n/**\n * Helper function to transform multiple models' encrypted fields into PostgreSQL composite types\n */\nexport function bulkModelsToEncryptedPgComposites<\n T extends Record<string, unknown>,\n>(models: T[]): T[] {\n return models.map((model) => modelToEncryptedPgComposites(model))\n}\n\nexport function toFfiKeysetIdentifier(\n keyset: KeysetIdentifier | undefined,\n): KeysetIdentifierFfi | undefined {\n if (!keyset) return undefined\n\n if ('name' in keyset) {\n return { Name: keyset.name }\n }\n\n return { Uuid: keyset.id }\n}\n\n/**\n * Helper function to check if a value is an encrypted payload\n */\nexport function isEncryptedPayload(value: unknown): value is Encrypted {\n if (value === null) return false\n if (typeof value !== 'object') return false\n\n const obj = value as Record<string, unknown>\n\n // Must have version field (number)\n if (!('v' in obj) || typeof obj.v !== 'number') return false\n\n // Must have index field (object)\n if (!('i' in obj) || typeof obj.i !== 'object') return false\n\n // Must have either ciphertext (c) or searchable vector (sv)\n if (!('c' in obj) && !('sv' in obj)) return false\n\n return true\n}\n\nexport {\n toJsonPath,\n buildNestedObject,\n parseJsonbPath,\n} from './jsonb'\n","import type { Encrypted } from '@/types'\nimport { z } from 'zod'\n\n// ------------------------\n// Zod schemas\n// ------------------------\n\n/**\n * Allowed cast types for CipherStash schema fields.\n *\n * **Possible values:**\n * - `\"bigint\"`\n * - `\"boolean\"`\n * - `\"date\"`\n * - `\"number\"`\n * - `\"string\"`\n * - `\"json\"`\n *\n * @remarks\n * This is a Zod enum used at runtime to validate schema definitions.\n * Use {@link CastAs} when typing your own code.\n *\n * @internal\n */\nexport const castAsEnum = z\n .enum(['bigint', 'boolean', 'date', 'number', 'string', 'json'])\n .default('string')\n\nconst tokenFilterSchema = z.object({\n kind: z.literal('downcase'),\n})\n\nconst tokenizerSchema = z\n .union([\n z.object({\n kind: z.literal('standard'),\n }),\n z.object({\n kind: z.literal('ngram'),\n token_length: z.number(),\n }),\n ])\n .default({ kind: 'ngram', token_length: 3 })\n .optional()\n\nconst oreIndexOptsSchema = z.object({})\n\nconst uniqueIndexOptsSchema = z.object({\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n})\n\nconst matchIndexOptsSchema = z.object({\n tokenizer: tokenizerSchema,\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n k: z.number().default(6).optional(),\n m: z.number().default(2048).optional(),\n include_original: z.boolean().default(false).optional(),\n})\n\nconst steVecIndexOptsSchema = z.object({\n prefix: z.string(),\n})\n\nconst indexesSchema = z\n .object({\n ore: oreIndexOptsSchema.optional(),\n unique: uniqueIndexOptsSchema.optional(),\n match: matchIndexOptsSchema.optional(),\n ste_vec: steVecIndexOptsSchema.optional(),\n })\n .default({})\n\nconst columnSchema = z\n .object({\n cast_as: castAsEnum,\n indexes: indexesSchema,\n })\n .default({})\n\nconst tableSchema = z.record(columnSchema).default({})\n\nconst tablesSchema = z.record(tableSchema).default({})\n\n/** @internal */\nexport const encryptConfigSchema = z.object({\n v: z.number(),\n tables: tablesSchema,\n})\n\n// ------------------------\n// Type definitions\n// ------------------------\n\n/**\n * Type-safe alias for {@link castAsEnum} used to specify the *unencrypted* data type of a column or value.\n * This is important because once encrypted, all data is stored as binary blobs.\n *\n * @see {@link castAsEnum} for possible values.\n */\nexport type CastAs = z.infer<typeof castAsEnum>\nexport type TokenFilter = z.infer<typeof tokenFilterSchema>\nexport type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>\nexport type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>\nexport type UniqueIndexOpts = z.infer<typeof uniqueIndexOptsSchema>\nexport type OreIndexOpts = z.infer<typeof oreIndexOptsSchema>\nexport type ColumnSchema = z.infer<typeof columnSchema>\n\nexport type ProtectTableColumn = {\n [key: string]:\n | ProtectColumn\n | {\n [key: string]:\n | ProtectValue\n | {\n [key: string]:\n | ProtectValue\n | {\n [key: string]: ProtectValue\n }\n }\n }\n}\nexport type EncryptConfig = z.infer<typeof encryptConfigSchema>\n\n// ------------------------\n// Interface definitions\n// ------------------------\nexport class ProtectValue {\n private valueName: string\n private castAsValue: CastAs\n\n constructor(valueName: string) {\n this.valueName = valueName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this value.\n *\n * By default all values are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `ProtectValue` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedValue } from \"@cipherstash/stack/schema\"\n *\n * const age = encryptedValue(\"age\").dataType(\"number\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: {},\n }\n }\n\n getName() {\n return this.valueName\n }\n}\n\nexport class ProtectColumn {\n private columnName: string\n private castAsValue: CastAs\n private indexesValue: {\n ore?: OreIndexOpts\n unique?: UniqueIndexOpts\n match?: Required<MatchIndexOpts>\n ste_vec?: SteVecIndexOpts\n } = {}\n\n constructor(columnName: string) {\n this.columnName = columnName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this column.\n *\n * By default all columns are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `ProtectColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const dateOfBirth = encryptedColumn(\"date_of_birth\").dataType(\"date\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n /**\n * Enable Order-Revealing Encryption (ORE) indexing on this column.\n *\n * ORE allows sorting, comparison, and range queries on encrypted data.\n * Use with `encryptQuery` and `queryType: 'orderAndRange'`.\n *\n * @returns This `ProtectColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").orderAndRange(),\n * })\n * ```\n */\n orderAndRange() {\n this.indexesValue.ore = {}\n return this\n }\n\n /**\n * Enable an exact-match (unique) index on this column.\n *\n * Allows equality queries on encrypted data. Use with `encryptQuery`\n * and `queryType: 'equality'`.\n *\n * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).\n * When omitted, no token filters are applied.\n * @returns This `ProtectColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n * ```\n */\n equality(tokenFilters?: TokenFilter[]) {\n this.indexesValue.unique = {\n token_filters: tokenFilters ?? [],\n }\n return this\n }\n\n /**\n * Enable a full-text / fuzzy search (match) index on this column.\n *\n * Uses n-gram tokenization by default for substring and fuzzy matching.\n * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.\n *\n * @param opts - Optional match index configuration. Defaults to 3-character ngram\n * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.\n * @returns This `ProtectColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").freeTextSearch(),\n * })\n *\n * // With custom options\n * const posts = encryptedTable(\"posts\", {\n * body: encryptedColumn(\"body\").freeTextSearch({\n * tokenizer: { kind: \"ngram\", token_length: 4 },\n * k: 8,\n * m: 4096,\n * }),\n * })\n * ```\n */\n freeTextSearch(opts?: MatchIndexOpts) {\n // Provide defaults\n this.indexesValue.match = {\n tokenizer: opts?.tokenizer ?? { kind: 'ngram', token_length: 3 },\n token_filters: opts?.token_filters ?? [\n {\n kind: 'downcase',\n },\n ],\n k: opts?.k ?? 6,\n m: opts?.m ?? 2048,\n include_original: opts?.include_original ?? true,\n }\n return this\n }\n\n /**\n * Configure this column for searchable encrypted JSON (STE-Vec).\n *\n * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and\n * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the\n * data type to `'json'`.\n *\n * When used with `encryptQuery`, the query operation is auto-inferred from\n * the plaintext type: strings become selector queries, objects/arrays become\n * containment queries.\n *\n * @returns This `ProtectColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const documents = encryptedTable(\"documents\", {\n * metadata: encryptedColumn(\"metadata\").searchableJson(),\n * })\n * ```\n */\n searchableJson() {\n this.castAsValue = 'json'\n this.indexesValue.ste_vec = { prefix: 'enabled' }\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: this.indexesValue,\n }\n }\n\n getName() {\n return this.columnName\n }\n}\n\ninterface TableDefinition {\n tableName: string\n columns: Record<string, ColumnSchema>\n}\n\nexport class ProtectTable<T extends ProtectTableColumn> {\n constructor(\n public readonly tableName: string,\n private readonly columnBuilders: T,\n ) {}\n\n /**\n * Compile this table schema into a `TableDefinition` used internally by the encryption client.\n *\n * Iterates over all column builders, calls `.build()` on each, and assembles\n * the final `{ tableName, columns }` structure. For `searchableJson()` columns,\n * the STE-Vec prefix is automatically set to `\"<tableName>/<columnName>\"`.\n *\n * @returns A `TableDefinition` containing the table name and built column configs.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const definition = users.build()\n * // { tableName: \"users\", columns: { email: { cast_as: \"string\", indexes: { unique: ... } } } }\n * ```\n */\n build(): TableDefinition {\n const builtColumns: Record<string, ColumnSchema> = {}\n\n const processColumn = (\n builder:\n | ProtectColumn\n | Record<\n string,\n | ProtectValue\n | Record<\n string,\n | ProtectValue\n | Record<string, ProtectValue | Record<string, ProtectValue>>\n >\n >,\n colName: string,\n ) => {\n if (builder instanceof ProtectColumn) {\n const builtColumn = builder.build()\n\n // Hanlde building the ste_vec index for JSON columns so users don't have to pass the prefix.\n if (\n builtColumn.cast_as === 'json' &&\n builtColumn.indexes.ste_vec?.prefix === 'enabled'\n ) {\n builtColumns[colName] = {\n ...builtColumn,\n indexes: {\n ...builtColumn.indexes,\n ste_vec: {\n prefix: `${this.tableName}/${colName}`,\n },\n },\n }\n } else {\n builtColumns[colName] = builtColumn\n }\n } else {\n for (const [key, value] of Object.entries(builder)) {\n if (value instanceof ProtectValue) {\n builtColumns[value.getName()] = value.build()\n } else {\n processColumn(value, key)\n }\n }\n }\n }\n\n for (const [colName, builder] of Object.entries(this.columnBuilders)) {\n processColumn(builder, colName)\n }\n\n return {\n tableName: this.tableName,\n columns: builtColumns,\n }\n }\n}\n\n// ------------------------\n// Schema type inference helpers\n// ------------------------\n\n/**\n * Infer the plaintext (decrypted) type from a ProtectTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * name: encryptedColumn(\"name\"),\n * })\n *\n * type UserPlaintext = InferPlaintext<typeof users>\n * // => { email: string; name: string }\n * ```\n */\nexport type InferPlaintext<T extends ProtectTable<any>> =\n T extends ProtectTable<infer C>\n ? {\n [K in keyof C as C[K] extends ProtectColumn | ProtectValue\n ? K\n : never]: string\n }\n : never\n\n/**\n * Infer the encrypted type from a ProtectTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * type UserEncrypted = InferEncrypted<typeof users>\n * // => { email: Encrypted }\n * ```\n */\nexport type InferEncrypted<T extends ProtectTable<any>> =\n T extends ProtectTable<infer C>\n ? {\n [K in keyof C as C[K] extends ProtectColumn | ProtectValue\n ? K\n : never]: Encrypted\n }\n : never\n\n// ------------------------\n// User facing functions\n// ------------------------\n\n/**\n * Define an encrypted table schema.\n *\n * Creates a `ProtectTable` that maps a database table name to a set of encrypted\n * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`\n * when initializing the client.\n *\n * The returned object is also a proxy that exposes each column builder directly,\n * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,\n * and `encryptQuery`.\n *\n * @param tableName - The name of the database table this schema represents.\n * @param columns - An object whose keys are logical column names and values are\n * `ProtectColumn` instances created with {@link encryptedColumn}.\n * @returns A `ProtectTable<T> & T` that can be used as both a schema definition\n * and a column accessor.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch(),\n * address: encryptedColumn(\"address\"),\n * })\n *\n * // Use as schema\n * const client = await Encryption({ schemas: [users] })\n *\n * // Use as column accessor\n * await client.encrypt(\"hello@example.com\", { column: users.email, table: users })\n * ```\n */\nexport function encryptedTable<T extends ProtectTableColumn>(\n tableName: string,\n columns: T,\n): ProtectTable<T> & T {\n const tableBuilder = new ProtectTable(tableName, columns) as ProtectTable<T> &\n T\n\n for (const [colName, colBuilder] of Object.entries(columns)) {\n ;(tableBuilder as ProtectTableColumn)[colName] = colBuilder\n }\n\n return tableBuilder\n}\n\n/**\n * Define an encrypted column within a table schema.\n *\n * Creates a `ProtectColumn` builder for the given column name. Chain index\n * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,\n * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption\n * and the plaintext data type.\n *\n * @param columnName - The name of the database column to encrypt.\n * @returns A new `ProtectColumn` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch().orderAndRange(),\n * })\n * ```\n */\nexport function encryptedColumn(columnName: string) {\n return new ProtectColumn(columnName)\n}\n\n/**\n * Define an encrypted value for use in nested or structured schemas.\n *\n * `encryptedValue` is similar to {@link encryptedColumn} but creates a `ProtectValue`\n * intended for nested fields within a table schema. It supports `.dataType()`\n * for specifying the plaintext type.\n *\n * @param valueName - The name of the value field.\n * @returns A new `ProtectValue` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedValue } from \"@cipherstash/stack/schema\"\n *\n * const orders = encryptedTable(\"orders\", {\n * details: {\n * amount: encryptedValue(\"amount\").dataType(\"number\"),\n * currency: encryptedValue(\"currency\"),\n * },\n * })\n * ```\n */\nexport function encryptedValue(valueName: string) {\n return new ProtectValue(valueName)\n}\n\n// ------------------------\n// Internal functions\n// ------------------------\n\n/** @internal */\nexport function buildEncryptConfig(\n ...protectTables: Array<ProtectTable<ProtectTableColumn>>\n): EncryptConfig {\n const config: EncryptConfig = {\n v: 2,\n tables: {},\n }\n\n for (const tb of protectTables) {\n const tableDef = tb.build()\n config.tables[tableDef.tableName] = tableDef.columns\n }\n\n return config\n}\n","import type { ProtectColumn, ProtectTable, ProtectTableColumn } 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: ProtectTable<ProtectTableColumn>,\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/ffi'\nimport type { AuditConfig } from '@/encryption/ffi/operations/base-operation'\nimport {\n bulkModelsToEncryptedPgComposites,\n modelToEncryptedPgComposites,\n} from '@/encryption/helpers'\nimport type { LockContext } from '@/identity'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport { ProtectColumn } from '@/schema'\nimport type { ScalarQueryTerm } from '@/types'\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: ProtectTable<ProtectTableColumn>\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: ProtectTable<ProtectTableColumn>,\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 // 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 error: EncryptedSupabaseError = {\n message: err instanceof Error ? err.message : String(err),\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 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 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 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 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 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, ProtectColumn> {\n const map: Record<string, ProtectColumn> = {}\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 ProtectColumn) {\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"],"mappings":"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","names":["baseOp","op","result","decrypted"]}
|
|
1
|
+
{"version":3,"sources":["../../src/supabase/index.ts","../../src/encryption/helpers/index.ts","../../src/schema/index.ts","../../src/supabase/helpers.ts","../../src/supabase/query-builder.ts"],"sourcesContent":["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","import type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types'\nimport type {\n Encrypted as CipherStashEncrypted,\n KeysetIdentifier as KeysetIdentifierFfi,\n} from '@cipherstash/protect-ffi'\n\nexport type EncryptedPgComposite = {\n data: Encrypted\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite type.\n * Use this when inserting data via Supabase or similar clients.\n */\nexport function encryptedToPgComposite(obj: Encrypted): EncryptedPgComposite {\n return {\n data: obj,\n }\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite literal string.\n * Use this when querying with `.eq()` or similar equality operations in Supabase.\n *\n * @example\n * ```typescript\n * const literal = encryptedToCompositeLiteral(encrypted)\n * await supabase.from('table').select().eq('column', literal)\n * ```\n */\nexport function encryptedToCompositeLiteral(obj: CipherStashEncrypted): string {\n if (obj === null) {\n throw new Error('encryptedToCompositeLiteral: obj cannot be null')\n }\n return `(${JSON.stringify(JSON.stringify(obj))})`\n}\n\n/**\n * Helper function to transform an encrypted payload into an escaped PostgreSQL composite literal string.\n * Use this when you need the composite literal format to be escaped as a string value.\n *\n * @example\n * ```typescript\n * const escapedLiteral = encryptedToEscapedCompositeLiteral(encrypted)\n * ```\n */\nexport function encryptedToEscapedCompositeLiteral(\n obj: CipherStashEncrypted,\n): string {\n if (obj === null) {\n throw new Error('encryptedToEscapedCompositeLiteral: obj cannot be null')\n }\n return JSON.stringify(encryptedToCompositeLiteral(obj))\n}\n\n/**\n * Format an encrypted result based on the requested return type.\n *\n * - `'composite-literal'` → PostgreSQL composite literal string `(\"json\")`\n * - `'escaped-composite-literal'` → escaped variant `\"(\\\"json\\\")\"`\n * - default (`'eql'` or omitted) → raw encrypted object\n */\nexport function formatEncryptedResult(\n encrypted: CipherStashEncrypted,\n returnType?: string,\n): EncryptedQueryResult {\n if (returnType === 'composite-literal') {\n return encryptedToCompositeLiteral(encrypted)\n }\n if (returnType === 'escaped-composite-literal') {\n return encryptedToEscapedCompositeLiteral(encrypted)\n }\n return encrypted\n}\n\n/**\n * Helper function to transform a model's encrypted fields into PostgreSQL composite types\n */\nexport function modelToEncryptedPgComposites<T extends Record<string, unknown>>(\n model: T,\n): T {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (isEncryptedPayload(value)) {\n result[key] = encryptedToPgComposite(value)\n } else {\n result[key] = value\n }\n }\n\n return result as T\n}\n\n/**\n * Helper function to transform multiple models' encrypted fields into PostgreSQL composite types\n */\nexport function bulkModelsToEncryptedPgComposites<\n T extends Record<string, unknown>,\n>(models: T[]): T[] {\n return models.map((model) => modelToEncryptedPgComposites(model))\n}\n\nexport function toFfiKeysetIdentifier(\n keyset: KeysetIdentifier | undefined,\n): KeysetIdentifierFfi | undefined {\n if (!keyset) return undefined\n\n if ('name' in keyset) {\n return { Name: keyset.name }\n }\n\n return { Uuid: keyset.id }\n}\n\n/**\n * Helper function to check if a value is an encrypted payload\n */\nexport function isEncryptedPayload(value: unknown): value is Encrypted {\n if (value === null) return false\n if (typeof value !== 'object') return false\n\n const obj = value as Record<string, unknown>\n\n // Must have version field (number)\n if (!('v' in obj) || typeof obj.v !== 'number') return false\n\n // Must have index field (object)\n if (!('i' in obj) || typeof obj.i !== 'object') return false\n\n // Must have either ciphertext (c) or searchable vector (sv)\n if (!('c' in obj) && !('sv' in obj)) return false\n\n return true\n}\n\nexport {\n toJsonPath,\n buildNestedObject,\n parseJsonbPath,\n} from './jsonb'\n","import type { Encrypted } from '@/types'\nimport { z } from 'zod'\n\n// ------------------------\n// Zod schemas\n// ------------------------\n\n/**\n * Allowed cast types for CipherStash schema fields.\n *\n * **Possible values:**\n * - `\"bigint\"`\n * - `\"boolean\"`\n * - `\"date\"`\n * - `\"number\"`\n * - `\"string\"`\n * - `\"json\"`\n *\n * @remarks\n * This is a Zod enum used at runtime to validate schema definitions.\n * Use {@link CastAs} when typing your own code.\n *\n * @internal\n */\nexport const castAsEnum = z\n .enum(['bigint', 'boolean', 'date', 'number', 'string', 'json'])\n .default('string')\n\nconst tokenFilterSchema = z.object({\n kind: z.literal('downcase'),\n})\n\nconst tokenizerSchema = z\n .union([\n z.object({\n kind: z.literal('standard'),\n }),\n z.object({\n kind: z.literal('ngram'),\n token_length: z.number(),\n }),\n ])\n .default({ kind: 'ngram', token_length: 3 })\n .optional()\n\nconst oreIndexOptsSchema = z.object({})\n\nconst uniqueIndexOptsSchema = z.object({\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n})\n\nconst matchIndexOptsSchema = z.object({\n tokenizer: tokenizerSchema,\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n k: z.number().default(6).optional(),\n m: z.number().default(2048).optional(),\n include_original: z.boolean().default(false).optional(),\n})\n\nconst steVecIndexOptsSchema = z.object({\n prefix: z.string(),\n})\n\nconst indexesSchema = z\n .object({\n ore: oreIndexOptsSchema.optional(),\n unique: uniqueIndexOptsSchema.optional(),\n match: matchIndexOptsSchema.optional(),\n ste_vec: steVecIndexOptsSchema.optional(),\n })\n .default({})\n\nconst columnSchema = z\n .object({\n cast_as: castAsEnum,\n indexes: indexesSchema,\n })\n .default({})\n\nconst tableSchema = z.record(columnSchema).default({})\n\nconst tablesSchema = z.record(tableSchema).default({})\n\n/** @internal */\nexport const encryptConfigSchema = z.object({\n v: z.number(),\n tables: tablesSchema,\n})\n\n// ------------------------\n// Type definitions\n// ------------------------\n\n/**\n * Type-safe alias for {@link castAsEnum} used to specify the *unencrypted* data type of a column or value.\n * This is important because once encrypted, all data is stored as binary blobs.\n *\n * @see {@link castAsEnum} for possible values.\n */\nexport type CastAs = z.infer<typeof castAsEnum>\nexport type TokenFilter = z.infer<typeof tokenFilterSchema>\nexport type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>\nexport type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>\nexport type UniqueIndexOpts = z.infer<typeof uniqueIndexOptsSchema>\nexport type OreIndexOpts = z.infer<typeof oreIndexOptsSchema>\nexport type ColumnSchema = z.infer<typeof columnSchema>\n\n/**\n * Shape of table columns: either top-level {@link EncryptedColumn} or nested\n * objects whose leaves are {@link EncryptedField}. Used with {@link encryptedTable}.\n */\nexport type EncryptedTableColumn = {\n [key: string]:\n | EncryptedColumn\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]: EncryptedField\n }\n }\n }\n}\nexport type EncryptConfig = z.infer<typeof encryptConfigSchema>\n\n// ------------------------\n// Interface definitions\n// ------------------------\n\n/**\n * Builder for a nested encrypted field (encrypted but not searchable).\n * Create with {@link encryptedField}. Use inside nested objects in {@link encryptedTable};\n * supports `.dataType()` for plaintext type. No index methods (equality, orderAndRange, etc.).\n */\nexport class EncryptedField {\n private valueName: string\n private castAsValue: CastAs\n\n constructor(valueName: string) {\n this.valueName = valueName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this field.\n *\n * By default all values are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedField` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const age = encryptedField(\"age\").dataType(\"number\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: {},\n }\n }\n\n getName() {\n return this.valueName\n }\n}\n\nexport class EncryptedColumn {\n private columnName: string\n private castAsValue: CastAs\n private indexesValue: {\n ore?: OreIndexOpts\n unique?: UniqueIndexOpts\n match?: Required<MatchIndexOpts>\n ste_vec?: SteVecIndexOpts\n } = {}\n\n constructor(columnName: string) {\n this.columnName = columnName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this column.\n *\n * By default all columns are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const dateOfBirth = encryptedColumn(\"date_of_birth\").dataType(\"date\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n /**\n * Enable Order-Revealing Encryption (ORE) indexing on this column.\n *\n * ORE allows sorting, comparison, and range queries on encrypted data.\n * Use with `encryptQuery` and `queryType: 'orderAndRange'`.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").orderAndRange(),\n * })\n * ```\n */\n orderAndRange() {\n this.indexesValue.ore = {}\n return this\n }\n\n /**\n * Enable an exact-match (unique) index on this column.\n *\n * Allows equality queries on encrypted data. Use with `encryptQuery`\n * and `queryType: 'equality'`.\n *\n * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).\n * When omitted, no token filters are applied.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n * ```\n */\n equality(tokenFilters?: TokenFilter[]) {\n this.indexesValue.unique = {\n token_filters: tokenFilters ?? [],\n }\n return this\n }\n\n /**\n * Enable a full-text / fuzzy search (match) index on this column.\n *\n * Uses n-gram tokenization by default for substring and fuzzy matching.\n * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.\n *\n * @param opts - Optional match index configuration. Defaults to 3-character ngram\n * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").freeTextSearch(),\n * })\n *\n * // With custom options\n * const posts = encryptedTable(\"posts\", {\n * body: encryptedColumn(\"body\").freeTextSearch({\n * tokenizer: { kind: \"ngram\", token_length: 4 },\n * k: 8,\n * m: 4096,\n * }),\n * })\n * ```\n */\n freeTextSearch(opts?: MatchIndexOpts) {\n // Provide defaults\n this.indexesValue.match = {\n tokenizer: opts?.tokenizer ?? { kind: 'ngram', token_length: 3 },\n token_filters: opts?.token_filters ?? [\n {\n kind: 'downcase',\n },\n ],\n k: opts?.k ?? 6,\n m: opts?.m ?? 2048,\n include_original: opts?.include_original ?? true,\n }\n return this\n }\n\n /**\n * Configure this column for searchable encrypted JSON (STE-Vec).\n *\n * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and\n * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the\n * data type to `'json'`.\n *\n * When used with `encryptQuery`, the query operation is auto-inferred from\n * the plaintext type: strings become selector queries, objects/arrays become\n * containment queries.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const documents = encryptedTable(\"documents\", {\n * metadata: encryptedColumn(\"metadata\").searchableJson(),\n * })\n * ```\n */\n searchableJson() {\n this.castAsValue = 'json'\n this.indexesValue.ste_vec = { prefix: 'enabled' }\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: this.indexesValue,\n }\n }\n\n getName() {\n return this.columnName\n }\n}\n\ninterface TableDefinition {\n tableName: string\n columns: Record<string, ColumnSchema>\n}\n\nexport class EncryptedTable<T extends EncryptedTableColumn> {\n /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */\n declare readonly _columnType: T\n\n constructor(\n public readonly tableName: string,\n private readonly columnBuilders: T,\n ) {}\n\n /**\n * Compile this table schema into a `TableDefinition` used internally by the encryption client.\n *\n * Iterates over all column builders, calls `.build()` on each, and assembles\n * the final `{ tableName, columns }` structure. For `searchableJson()` columns,\n * the STE-Vec prefix is automatically set to `\"<tableName>/<columnName>\"`.\n *\n * @returns A `TableDefinition` containing the table name and built column configs.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const definition = users.build()\n * // { tableName: \"users\", columns: { email: { cast_as: \"string\", indexes: { unique: ... } } } }\n * ```\n */\n build(): TableDefinition {\n const builtColumns: Record<string, ColumnSchema> = {}\n\n const processColumn = (\n builder:\n | EncryptedColumn\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n EncryptedField | Record<string, EncryptedField>\n >\n >\n >,\n colName: string,\n ) => {\n if (builder instanceof EncryptedColumn) {\n const builtColumn = builder.build()\n\n // Hanlde building the ste_vec index for JSON columns so users don't have to pass the prefix.\n if (\n builtColumn.cast_as === 'json' &&\n builtColumn.indexes.ste_vec?.prefix === 'enabled'\n ) {\n builtColumns[colName] = {\n ...builtColumn,\n indexes: {\n ...builtColumn.indexes,\n ste_vec: {\n prefix: `${this.tableName}/${colName}`,\n },\n },\n }\n } else {\n builtColumns[colName] = builtColumn\n }\n } else {\n for (const [key, value] of Object.entries(builder)) {\n if (value instanceof EncryptedField) {\n builtColumns[value.getName()] = value.build()\n } else {\n processColumn(value, key)\n }\n }\n }\n }\n\n for (const [colName, builder] of Object.entries(this.columnBuilders)) {\n processColumn(builder, colName)\n }\n\n return {\n tableName: this.tableName,\n columns: builtColumns,\n }\n }\n}\n\n// ------------------------\n// Schema type inference helpers\n// ------------------------\n\n/**\n * Infer the plaintext (decrypted) type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * name: encryptedColumn(\"name\"),\n * })\n *\n * type UserPlaintext = InferPlaintext<typeof users>\n * // => { email: string; name: string }\n * ```\n */\nexport type InferPlaintext<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: string\n }\n : never\n\n/**\n * Infer the encrypted type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * type UserEncrypted = InferEncrypted<typeof users>\n * // => { email: Encrypted }\n * ```\n */\nexport type InferEncrypted<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: Encrypted\n }\n : never\n\n// ------------------------\n// User facing functions\n// ------------------------\n\n/**\n * Define an encrypted table schema.\n *\n * Creates a `EncryptedTable` that maps a database table name to a set of encrypted\n * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`\n * when initializing the client.\n *\n * The returned object is also a proxy that exposes each column builder directly,\n * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,\n * and `encryptQuery`.\n *\n * @param tableName - The name of the database table this schema represents.\n * @param columns - An object whose keys are logical column names and values are\n * {@link EncryptedColumn} from {@link encryptedColumn}, or nested objects whose\n * leaves are {@link EncryptedField} from {@link encryptedField}.\n * @returns A `EncryptedTable<T> & T` that can be used as both a schema definition\n * and a column accessor.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch(),\n * address: encryptedColumn(\"address\"),\n * })\n *\n * // Use as schema\n * const client = await Encryption({ schemas: [users] })\n *\n * // Use as column accessor\n * await client.encrypt(\"hello@example.com\", { column: users.email, table: users })\n * ```\n */\nexport function encryptedTable<T extends EncryptedTableColumn>(\n tableName: string,\n columns: T,\n): EncryptedTable<T> & T {\n const tableBuilder = new EncryptedTable(\n tableName,\n columns,\n ) as EncryptedTable<T> & T\n\n for (const [colName, colBuilder] of Object.entries(columns)) {\n ;(tableBuilder as EncryptedTableColumn)[colName] = colBuilder\n }\n\n return tableBuilder\n}\n\n/**\n * Define an encrypted column within a table schema.\n *\n * Creates a `EncryptedColumn` builder for the given column name. Chain index\n * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,\n * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption\n * and the plaintext data type.\n *\n * @param columnName - The name of the database column to encrypt.\n * @returns A new `EncryptedColumn` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch().orderAndRange(),\n * })\n * ```\n */\nexport function encryptedColumn(columnName: string) {\n return new EncryptedColumn(columnName)\n}\n\n/**\n * Define an encrypted field for use in nested or structured schemas.\n *\n * `encryptedField` is similar to {@link encryptedColumn} but creates an {@link EncryptedField}\n * for nested fields that are encrypted but not searchable (no indexes). Use `.dataType()`\n * to specify the plaintext type.\n *\n * @param valueName - The name of the value field.\n * @returns A new `EncryptedField` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const orders = encryptedTable(\"orders\", {\n * details: {\n * amount: encryptedField(\"amount\").dataType(\"number\"),\n * currency: encryptedField(\"currency\"),\n * },\n * })\n * ```\n */\nexport function encryptedField(valueName: string) {\n return new EncryptedField(valueName)\n}\n\n// ------------------------\n// Internal functions\n// ------------------------\n\n/** @internal */\nexport function buildEncryptConfig(\n ...protectTables: Array<EncryptedTable<EncryptedTableColumn>>\n): EncryptConfig {\n const config: EncryptConfig = {\n v: 2,\n tables: {},\n }\n\n for (const tb of protectTables) {\n const tableDef = tb.build()\n config.tables[tableDef.tableName] = tableDef.columns\n }\n\n return config\n}\n","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 type { AuditConfig } from '@/encryption/operations/base-operation'\nimport {\n bulkModelsToEncryptedPgComposites,\n modelToEncryptedPgComposites,\n} from '@/encryption/helpers'\nimport type { LockContext } from '@/identity'\nimport type { EncryptedTable, EncryptedTableColumn } from '@/schema'\nimport { EncryptedColumn } from '@/schema'\nimport type { ScalarQueryTerm } from '@/types'\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 // 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 error: EncryptedSupabaseError = {\n message: err instanceof Error ? err.message : String(err),\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 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 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 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 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 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"],"mappings":"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","names":["baseOp","op","result","decrypted"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { E as EncryptionClient, A as AuditConfig } from '../client-
|
|
1
|
+
import { E as EncryptionClient, A as AuditConfig } from '../client-Bf0Xw2xo.cjs';
|
|
2
2
|
import { a as EncryptionError, d as LockContext } from '../index-9-Ya3fDK.cjs';
|
|
3
|
-
import {
|
|
3
|
+
import { f as EncryptedTable, g as EncryptedTableColumn } from '../types-public-0CzBV45X.cjs';
|
|
4
4
|
import '@byteslice/result';
|
|
5
5
|
import '@cipherstash/protect-ffi';
|
|
6
6
|
import 'zod';
|
|
@@ -11,7 +11,7 @@ type EncryptedSupabaseConfig = {
|
|
|
11
11
|
supabaseClient: SupabaseClientLike;
|
|
12
12
|
};
|
|
13
13
|
interface EncryptedSupabaseInstance {
|
|
14
|
-
from<T extends Record<string, unknown> = Record<string, unknown>>(tableName: string, schema:
|
|
14
|
+
from<T extends Record<string, unknown> = Record<string, unknown>>(tableName: string, schema: EncryptedTable<EncryptedTableColumn>): EncryptedQueryBuilder<T>;
|
|
15
15
|
}
|
|
16
16
|
type EncryptedSupabaseResponse<T> = {
|
|
17
17
|
data: T | null;
|
package/dist/supabase/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { E as EncryptionClient, A as AuditConfig } from '../client-
|
|
1
|
+
import { E as EncryptionClient, A as AuditConfig } from '../client-Kfp8OsPB.js';
|
|
2
2
|
import { a as EncryptionError, d as LockContext } from '../index-9-Ya3fDK.js';
|
|
3
|
-
import {
|
|
3
|
+
import { f as EncryptedTable, g as EncryptedTableColumn } from '../types-public-0CzBV45X.js';
|
|
4
4
|
import '@byteslice/result';
|
|
5
5
|
import '@cipherstash/protect-ffi';
|
|
6
6
|
import 'zod';
|
|
@@ -11,7 +11,7 @@ type EncryptedSupabaseConfig = {
|
|
|
11
11
|
supabaseClient: SupabaseClientLike;
|
|
12
12
|
};
|
|
13
13
|
interface EncryptedSupabaseInstance {
|
|
14
|
-
from<T extends Record<string, unknown> = Record<string, unknown>>(tableName: string, schema:
|
|
14
|
+
from<T extends Record<string, unknown> = Record<string, unknown>>(tableName: string, schema: EncryptedTable<EncryptedTableColumn>): EncryptedQueryBuilder<T>;
|
|
15
15
|
}
|
|
16
16
|
type EncryptedSupabaseResponse<T> = {
|
|
17
17
|
data: T | null;
|
package/dist/supabase/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
modelToEncryptedPgComposites
|
|
4
4
|
} from "../chunk-SUYMGQBY.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
} from "../chunk-
|
|
6
|
+
EncryptedColumn
|
|
7
|
+
} from "../chunk-TBAIVO6T.js";
|
|
8
8
|
|
|
9
9
|
// src/supabase/helpers.ts
|
|
10
10
|
function getEncryptedColumnNames(schema) {
|
|
@@ -828,7 +828,7 @@ var EncryptedQueryBuilderImpl = class {
|
|
|
828
828
|
const schema = this.schema;
|
|
829
829
|
for (const colName of this.encryptedColumnNames) {
|
|
830
830
|
const col = schema[colName];
|
|
831
|
-
if (col instanceof
|
|
831
|
+
if (col instanceof EncryptedColumn) {
|
|
832
832
|
map[colName] = col;
|
|
833
833
|
}
|
|
834
834
|
}
|