@cipherstash/stack 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +670 -0
  4. package/dist/bin/stash.js +5049 -0
  5. package/dist/bin/stash.js.map +1 -0
  6. package/dist/chunk-2GZMIJFO.js +2400 -0
  7. package/dist/chunk-2GZMIJFO.js.map +1 -0
  8. package/dist/chunk-5DCT6YU2.js +138 -0
  9. package/dist/chunk-5DCT6YU2.js.map +1 -0
  10. package/dist/chunk-7XRPN2KX.js +336 -0
  11. package/dist/chunk-7XRPN2KX.js.map +1 -0
  12. package/dist/chunk-SJ7JO4ME.js +28 -0
  13. package/dist/chunk-SJ7JO4ME.js.map +1 -0
  14. package/dist/chunk-SUYMGQBY.js +67 -0
  15. package/dist/chunk-SUYMGQBY.js.map +1 -0
  16. package/dist/client-BxJG56Ey.d.cts +647 -0
  17. package/dist/client-DtGq9dJp.d.ts +647 -0
  18. package/dist/client.cjs +347 -0
  19. package/dist/client.cjs.map +1 -0
  20. package/dist/client.d.cts +7 -0
  21. package/dist/client.d.ts +7 -0
  22. package/dist/client.js +11 -0
  23. package/dist/client.js.map +1 -0
  24. package/dist/drizzle/index.cjs +1528 -0
  25. package/dist/drizzle/index.cjs.map +1 -0
  26. package/dist/drizzle/index.d.cts +350 -0
  27. package/dist/drizzle/index.d.ts +350 -0
  28. package/dist/drizzle/index.js +1212 -0
  29. package/dist/drizzle/index.js.map +1 -0
  30. package/dist/dynamodb/index.cjs +382 -0
  31. package/dist/dynamodb/index.cjs.map +1 -0
  32. package/dist/dynamodb/index.d.cts +125 -0
  33. package/dist/dynamodb/index.d.ts +125 -0
  34. package/dist/dynamodb/index.js +355 -0
  35. package/dist/dynamodb/index.js.map +1 -0
  36. package/dist/identity/index.cjs +271 -0
  37. package/dist/identity/index.cjs.map +1 -0
  38. package/dist/identity/index.d.cts +3 -0
  39. package/dist/identity/index.d.ts +3 -0
  40. package/dist/identity/index.js +117 -0
  41. package/dist/identity/index.js.map +1 -0
  42. package/dist/index-9-Ya3fDK.d.cts +169 -0
  43. package/dist/index-9-Ya3fDK.d.ts +169 -0
  44. package/dist/index.cjs +2915 -0
  45. package/dist/index.cjs.map +1 -0
  46. package/dist/index.d.cts +22 -0
  47. package/dist/index.d.ts +22 -0
  48. package/dist/index.js +23 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/schema/index.cjs +368 -0
  51. package/dist/schema/index.cjs.map +1 -0
  52. package/dist/schema/index.d.cts +4 -0
  53. package/dist/schema/index.d.ts +4 -0
  54. package/dist/schema/index.js +23 -0
  55. package/dist/schema/index.js.map +1 -0
  56. package/dist/secrets/index.cjs +3207 -0
  57. package/dist/secrets/index.cjs.map +1 -0
  58. package/dist/secrets/index.d.cts +227 -0
  59. package/dist/secrets/index.d.ts +227 -0
  60. package/dist/secrets/index.js +323 -0
  61. package/dist/secrets/index.js.map +1 -0
  62. package/dist/supabase/index.cjs +1113 -0
  63. package/dist/supabase/index.cjs.map +1 -0
  64. package/dist/supabase/index.d.cts +144 -0
  65. package/dist/supabase/index.d.ts +144 -0
  66. package/dist/supabase/index.js +864 -0
  67. package/dist/supabase/index.js.map +1 -0
  68. package/dist/types-public-BCj1L4fi.d.cts +1013 -0
  69. package/dist/types-public-BCj1L4fi.d.ts +1013 -0
  70. package/dist/types-public.cjs +40 -0
  71. package/dist/types-public.cjs.map +1 -0
  72. package/dist/types-public.d.cts +4 -0
  73. package/dist/types-public.d.ts +4 -0
  74. package/dist/types-public.js +7 -0
  75. package/dist/types-public.js.map +1 -0
  76. package/package.json +202 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/secrets/index.ts","../../src/encryption/helpers/index.ts","../../src/errors/index.ts","../../src/schema/index.ts","../../src/utils/config/index.ts","../../src/utils/logger/index.ts","../../src/encryption/ffi/index.ts","../../src/encryption/ffi/helpers/type-guards.ts","../../src/encryption/ffi/helpers/error-code.ts","../../src/encryption/ffi/operations/batch-encrypt-query.ts","../../src/types.ts","../../src/encryption/ffi/helpers/infer-index-type.ts","../../src/encryption/ffi/helpers/validation.ts","../../src/encryption/ffi/operations/base-operation.ts","../../src/encryption/ffi/operations/bulk-decrypt.ts","../../src/encryption/ffi/operations/bulk-decrypt-models.ts","../../src/encryption/ffi/model-helpers.ts","../../src/encryption/ffi/operations/bulk-encrypt.ts","../../src/encryption/ffi/operations/bulk-encrypt-models.ts","../../src/encryption/ffi/operations/decrypt.ts","../../src/encryption/ffi/operations/decrypt-model.ts","../../src/encryption/ffi/operations/encrypt.ts","../../src/encryption/ffi/operations/encrypt-model.ts","../../src/encryption/ffi/operations/encrypt-query.ts","../../src/index.ts"],"sourcesContent":["/**\n * Placeholder: Corrected Secrets client interface\n *\n * This file reflects the actual dashboard API endpoints as implemented in:\n * apps/dashboard/src/app/api/secrets/{get,set,list,get-many,delete}/route.ts\n *\n * Key corrections from the original interface:\n * 1. get, list, get-many are GET endpoints (not POST) with query params\n * 2. get-many takes a comma-separated `names` string (not a JSON array)\n * 3. set and delete return { success, message } (not void)\n * 4. SecretMetadata fields (id, createdAt, updatedAt) are non-optional\n * 5. GetSecretResponse fields (createdAt, updatedAt) are non-optional\n * 6. get-many enforces min 2 names (comma required) and max 100 names\n */\n\nimport type { EncryptionClient } from '@/encryption/ffi'\nimport { encryptedToPgComposite } from '@/encryption/helpers'\nimport { Encryption } from '@/index'\nimport { encryptedColumn, encryptedTable } from '@/schema'\nimport type { Encrypted } from '@/types'\nimport type { Result } from '@byteslice/result'\nimport { extractWorkspaceIdFromCrn } from '../utils/config/index.js'\n\nexport type SecretName = string\nexport type SecretValue = string\n\n/**\n * Discriminated error type for secrets operations.\n */\nexport type SecretsErrorType =\n | 'ApiError'\n | 'NetworkError'\n | 'ClientError'\n | 'EncryptionError'\n | 'DecryptionError'\n\n/**\n * Error returned by secrets operations.\n */\nexport interface SecretsError {\n type: SecretsErrorType\n message: string\n}\n\n/**\n * Configuration options for initializing the Stash client\n */\nexport interface SecretsConfig {\n workspaceCRN: string\n clientId: string\n clientKey: string\n environment: string\n apiKey: string\n accessKey?: string\n}\n\n/**\n * Secret metadata returned from the API (list endpoint).\n * All fields are always present in API responses.\n */\nexport interface SecretMetadata {\n id: string\n name: string\n environment: string\n createdAt: string\n updatedAt: string\n}\n\n/**\n * API response for listing secrets.\n * GET /api/secrets/list?workspaceId=...&environment=...\n */\nexport interface ListSecretsResponse {\n environment: string\n secrets: SecretMetadata[]\n}\n\n/**\n * API response for getting a single secret.\n * GET /api/secrets/get?workspaceId=...&environment=...&name=...\n *\n * The `encryptedValue` is the raw value stored in the vault's `value` column,\n * which is the `{ data: Encrypted }` object that was passed to the set endpoint.\n */\nexport interface GetSecretResponse {\n name: string\n environment: string\n encryptedValue: {\n data: Encrypted\n }\n createdAt: string\n updatedAt: string\n}\n\n/**\n * API response for getting multiple secrets.\n * GET /api/secrets/get-many?workspaceId=...&environment=...&names=name1,name2,...\n *\n * Returns an array of GetSecretResponse objects.\n * Constraints:\n * - `names` must be comma-separated (minimum 2 names)\n * - Maximum 100 names per request\n */\nexport type GetManySecretsResponse = GetSecretResponse[]\n\n/**\n * API response for setting a secret.\n * POST /api/secrets/set\n */\nexport interface SetSecretResponse {\n success: true\n message: string\n}\n\n/**\n * API request body for setting a secret.\n * POST /api/secrets/set\n */\nexport interface SetSecretRequest {\n workspaceId: string\n environment: string\n name: string\n encryptedValue: {\n data: Encrypted\n }\n}\n\n/**\n * API response for deleting a secret.\n * POST /api/secrets/delete\n */\nexport interface DeleteSecretResponse {\n success: true\n message: string\n}\n\n/**\n * API request body for deleting a secret.\n * POST /api/secrets/delete\n */\nexport interface DeleteSecretRequest {\n workspaceId: string\n environment: string\n name: string\n}\n\n/**\n * API error response for plan limit violations (403).\n * Returned by POST /api/secrets/set when the workspace has reached its secret limit.\n */\nexport interface PlanLimitError {\n error: string\n code: 'PLAN_LIMIT_REACHED'\n}\n\nexport interface DecryptedSecretResponse {\n name: string\n environment: string\n value: string\n createdAt: string\n updatedAt: string\n}\n\n/**\n * The Secrets client provides a high-level API for managing encrypted secrets\n * stored in CipherStash. Secrets are encrypted locally before being sent to\n * the API, ensuring end-to-end encryption.\n */\nexport class Secrets {\n private encryptionClient: EncryptionClient | null = null\n private config: SecretsConfig\n private readonly apiBaseUrl =\n process.env.STASH_API_URL || 'https://dashboard.cipherstash.com/api/secrets'\n private readonly secretsSchema = encryptedTable('secrets', {\n value: encryptedColumn('value'),\n })\n\n constructor(config: SecretsConfig) {\n this.config = config\n }\n\n private initPromise: Promise<void> | null = null\n\n /**\n * Initialize the Secrets client and underlying Encryption client\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = this._doInit()\n }\n return this.initPromise\n }\n\n private async _doInit(): Promise<void> {\n this.encryptionClient = await Encryption({\n schemas: [this.secretsSchema],\n config: {\n workspaceCrn: this.config.workspaceCRN,\n clientId: this.config.clientId,\n clientKey: this.config.clientKey,\n accessKey: this.config.apiKey,\n keyset: {\n name: this.config.environment,\n },\n },\n })\n }\n\n /**\n * Get the authorization header for API requests\n */\n private getAuthHeader(): string {\n return `Bearer ${this.config.apiKey}`\n }\n\n /**\n * Make an API request with error handling.\n *\n * For GET requests, `params` are appended as URL query parameters.\n * For POST requests, `body` is sent as JSON in the request body.\n */\n private async apiRequest<T>(\n method: 'GET' | 'POST',\n path: string,\n options?: {\n body?: unknown\n params?: Record<string, string>\n },\n ): Promise<Result<T, SecretsError>> {\n try {\n let url = `${this.apiBaseUrl}${path}`\n\n if (options?.params) {\n const searchParams = new URLSearchParams(options.params)\n url = `${url}?${searchParams.toString()}`\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: this.getAuthHeader(),\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n let errorMessage = `API request failed with status ${response.status}`\n try {\n const errorJson = JSON.parse(errorText)\n errorMessage = errorJson.message || errorJson.error || errorMessage\n } catch {\n errorMessage = errorText || errorMessage\n }\n\n return {\n failure: {\n type: 'ApiError',\n message: errorMessage,\n },\n }\n }\n\n const data = await response.json()\n return { data }\n } catch (error) {\n return {\n failure: {\n type: 'NetworkError',\n message:\n error instanceof Error\n ? error.message\n : 'Unknown network error occurred',\n },\n }\n }\n }\n\n /**\n * Store an encrypted secret in the vault.\n * The value is encrypted locally before being sent to the API.\n *\n * API: POST /api/secrets/set\n *\n * @param name - The name of the secret\n * @param value - The plaintext value to encrypt and store\n * @returns A Result containing the API response or an error\n */\n async set(\n name: SecretName,\n value: SecretValue,\n ): Promise<Result<SetSecretResponse, SecretsError>> {\n await this.ensureInitialized()\n\n if (!this.encryptionClient) {\n return {\n failure: {\n type: 'ClientError',\n message: 'Failed to initialize Encryption client',\n },\n }\n }\n\n // Encrypt the value locally\n const encryptResult = await this.encryptionClient.encrypt(value, {\n column: this.secretsSchema.value,\n table: this.secretsSchema,\n })\n\n if (encryptResult.failure) {\n return {\n failure: {\n type: 'EncryptionError',\n message: encryptResult.failure.message,\n },\n }\n }\n\n // Extract workspaceId from CRN\n const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN)\n\n // Send encrypted value to API\n return await this.apiRequest<SetSecretResponse>('POST', '/set', {\n body: {\n workspaceId,\n environment: this.config.environment,\n name,\n encryptedValue: encryptedToPgComposite(encryptResult.data),\n },\n })\n }\n\n /**\n * Retrieve and decrypt a secret from the vault.\n * The secret is decrypted locally after retrieval.\n *\n * API: GET /api/secrets/get?workspaceId=...&environment=...&name=...\n *\n * @param name - The name of the secret to retrieve\n * @returns A Result containing the decrypted value or an error\n */\n async get(name: SecretName): Promise<Result<SecretValue, SecretsError>> {\n await this.ensureInitialized()\n\n if (!this.encryptionClient) {\n return {\n failure: {\n type: 'ClientError',\n message: 'Failed to initialize Encryption client',\n },\n }\n }\n\n // Extract workspaceId from CRN\n const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN)\n\n // Fetch encrypted value from API via GET with query params\n const apiResult = await this.apiRequest<GetSecretResponse>('GET', '/get', {\n params: {\n workspaceId,\n environment: this.config.environment,\n name,\n },\n })\n\n if (apiResult.failure) {\n return apiResult\n }\n\n // Decrypt the value locally\n const decryptResult = await this.encryptionClient.decrypt(\n apiResult.data.encryptedValue.data,\n )\n\n if (decryptResult.failure) {\n return {\n failure: {\n type: 'DecryptionError',\n message: decryptResult.failure.message,\n },\n }\n }\n\n if (typeof decryptResult.data !== 'string') {\n return {\n failure: {\n type: 'DecryptionError',\n message: 'Decrypted value is not a string',\n },\n }\n }\n\n return { data: decryptResult.data }\n }\n\n /**\n * Retrieve and decrypt many secrets from the vault.\n * The secrets are decrypted locally after retrieval.\n * This method only triggers a single network request to the ZeroKMS.\n *\n * API: GET /api/secrets/get-many?workspaceId=...&environment=...&names=name1,name2,...\n *\n * Constraints:\n * - Minimum 2 secret names required\n * - Maximum 100 secret names per request\n *\n * @param names - The names of the secrets to retrieve (min 2, max 100)\n * @returns A Result containing an object mapping secret names to their decrypted values\n */\n async getMany(\n names: SecretName[],\n ): Promise<Result<Record<SecretName, SecretValue>, SecretsError>> {\n await this.ensureInitialized()\n\n if (!this.encryptionClient) {\n return {\n failure: {\n type: 'ClientError',\n message: 'Failed to initialize Encryption client',\n },\n }\n }\n\n if (names.length < 2) {\n return {\n failure: {\n type: 'ClientError',\n message: 'At least 2 secret names are required for getMany',\n },\n }\n }\n\n if (names.length > 100) {\n return {\n failure: {\n type: 'ClientError',\n message: 'Maximum 100 secret names per request',\n },\n }\n }\n\n // Extract workspaceId from CRN\n const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN)\n\n // Fetch encrypted values from API via GET with comma-separated names\n const apiResult = await this.apiRequest<GetManySecretsResponse>(\n 'GET',\n '/get-many',\n {\n params: {\n workspaceId,\n environment: this.config.environment,\n names: names.join(','),\n },\n },\n )\n\n if (apiResult.failure) {\n return apiResult\n }\n\n const dataToDecrypt = apiResult.data.map((item) => ({\n name: item.name,\n value: item.encryptedValue.data,\n }))\n\n const decryptResult =\n await this.encryptionClient.bulkDecryptModels(dataToDecrypt)\n\n if (decryptResult.failure) {\n return {\n failure: {\n type: 'DecryptionError',\n message: decryptResult.failure.message,\n },\n }\n }\n\n // Transform array of decrypted secrets into an object keyed by secret name\n const decryptedSecrets =\n decryptResult.data as unknown as DecryptedSecretResponse[]\n const secretsMap: Record<SecretName, SecretValue> = {}\n\n for (const secret of decryptedSecrets) {\n if (secret.name && secret.value) {\n secretsMap[secret.name] = secret.value\n }\n }\n\n return { data: secretsMap }\n }\n\n /**\n * List all secrets in the environment.\n * Only names and metadata are returned; values remain encrypted.\n *\n * API: GET /api/secrets/list?workspaceId=...&environment=...\n *\n * @returns A Result containing the list of secrets or an error\n */\n async list(): Promise<Result<SecretMetadata[], SecretsError>> {\n // Extract workspaceId from CRN\n const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN)\n\n const apiResult = await this.apiRequest<ListSecretsResponse>(\n 'GET',\n '/list',\n {\n params: {\n workspaceId,\n environment: this.config.environment,\n },\n },\n )\n\n if (apiResult.failure) {\n return apiResult\n }\n\n return { data: apiResult.data.secrets }\n }\n\n /**\n * Delete a secret from the vault.\n *\n * API: POST /api/secrets/delete\n *\n * @param name - The name of the secret to delete\n * @returns A Result containing the API response or an error\n */\n async delete(\n name: SecretName,\n ): Promise<Result<DeleteSecretResponse, SecretsError>> {\n // Extract workspaceId from CRN\n const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN)\n\n return await this.apiRequest<DeleteSecretResponse>('POST', '/delete', {\n body: {\n workspaceId,\n environment: this.config.environment,\n name,\n },\n })\n }\n}\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 { ProtectErrorCode } from '@cipherstash/protect-ffi'\n\nexport const EncryptionErrorTypes = {\n ClientInitError: 'ClientInitError',\n EncryptionError: 'EncryptionError',\n DecryptionError: 'DecryptionError',\n LockContextError: 'LockContextError',\n CtsTokenError: 'CtsTokenError',\n}\n\n/**\n * Base error interface returned by all encryption operations.\n *\n * Every operation that can fail returns `Result<T, EncryptionError>`.\n * Use the `type` field to narrow to a specific error kind, or use\n * {@link StackError} for an exhaustive discriminated union.\n *\n * @example\n * ```typescript\n * const result = await client.encrypt(value, opts)\n * if (result.failure) {\n * switch (result.failure.type) {\n * case 'EncryptionError':\n * console.error('Encryption failed:', result.failure.message)\n * break\n * case 'LockContextError':\n * console.error('Lock context issue:', result.failure.message)\n * break\n * }\n * }\n * ```\n */\nexport interface EncryptionError {\n type: (typeof EncryptionErrorTypes)[keyof typeof EncryptionErrorTypes]\n message: string\n code?: ProtectErrorCode\n}\n\n// ---------------------------------------------------------------------------\n// Specific error types (discriminated union members)\n// ---------------------------------------------------------------------------\n\nexport interface ClientInitError {\n type: typeof EncryptionErrorTypes.ClientInitError\n message: string\n}\n\nexport interface EncryptionOperationError {\n type: typeof EncryptionErrorTypes.EncryptionError\n message: string\n code?: ProtectErrorCode\n}\n\nexport interface DecryptionOperationError {\n type: typeof EncryptionErrorTypes.DecryptionError\n message: string\n code?: ProtectErrorCode\n}\n\nexport interface LockContextError {\n type: typeof EncryptionErrorTypes.LockContextError\n message: string\n}\n\nexport interface CtsTokenError {\n type: typeof EncryptionErrorTypes.CtsTokenError\n message: string\n}\n\n/**\n * Discriminated union of all specific error types.\n *\n * Use `StackError` when you need exhaustive error handling via `switch` on the `type` field.\n *\n * @example\n * ```typescript\n * function handleError(error: StackError) {\n * switch (error.type) {\n * case 'ClientInitError':\n * // re-initialize client\n * break\n * case 'EncryptionError':\n * case 'DecryptionError':\n * // log and retry\n * break\n * case 'LockContextError':\n * // re-authenticate\n * break\n * case 'CtsTokenError':\n * // refresh token\n * break\n * default:\n * error satisfies never\n * }\n * }\n * ```\n */\nexport type StackError =\n | ClientInitError\n | EncryptionOperationError\n | DecryptionOperationError\n | LockContextError\n | CtsTokenError\n\n// ---------------------------------------------------------------------------\n// Error utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Safely extract an error message from an unknown thrown value.\n * Unlike `(error as Error).message`, this handles non-Error values gracefully.\n */\nexport function getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message\n if (typeof error === 'string') return error\n return String(error)\n}\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 fs from 'node:fs'\nimport path from 'node:path'\n\n/**\n * A lightweight function that parses a TOML-like string\n * and returns the `workspace_crn` value found under `[auth]`.\n *\n * @param tomlString The contents of the TOML file as a string.\n * @returns The workspace_crn if found, otherwise undefined.\n */\nfunction getWorkspaceCrn(tomlString: string): string | undefined {\n let currentSection = ''\n let workspaceCrn: string | undefined\n\n const lines = tomlString.split(/\\r?\\n/)\n\n for (const line of lines) {\n const trimmedLine = line.trim()\n\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n continue\n }\n\n const sectionMatch = trimmedLine.match(/^\\[([^\\]]+)\\]$/)\n if (sectionMatch) {\n currentSection = sectionMatch[1]\n continue\n }\n\n const kvMatch = trimmedLine.match(/^(\\w+)\\s*=\\s*\"([^\"]+)\"$/)\n if (kvMatch) {\n const [_, key, value] = kvMatch\n\n if (currentSection === 'auth' && key === 'workspace_crn') {\n workspaceCrn = value\n break\n }\n }\n }\n\n return workspaceCrn\n}\n\n/**\n * Extracts the workspace ID from a CRN string.\n * CRN format: crn:region.aws:ID\n *\n * @param crn The CRN string to extract from\n * @returns The workspace ID portion of the CRN\n */\nexport function extractWorkspaceIdFromCrn(crn: string): string {\n const match = crn.match(/crn:[^:]+:([^:]+)$/)\n if (!match) {\n throw new Error('Invalid CRN format')\n }\n return match[1]\n}\n\nexport function loadWorkSpaceId(suppliedCrn?: string): string {\n const configPath = path.join(process.cwd(), 'cipherstash.toml')\n\n if (suppliedCrn) {\n return extractWorkspaceIdFromCrn(suppliedCrn)\n }\n\n if (!fs.existsSync(configPath) && !process.env.CS_WORKSPACE_CRN) {\n throw new Error(\n 'You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable.',\n )\n }\n\n // Environment variables take precedence over config files\n if (process.env.CS_WORKSPACE_CRN) {\n return extractWorkspaceIdFromCrn(process.env.CS_WORKSPACE_CRN)\n }\n\n if (!fs.existsSync(configPath)) {\n throw new Error(\n 'You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable.',\n )\n }\n\n const tomlString = fs.readFileSync(configPath, 'utf8')\n const workspaceCrn = getWorkspaceCrn(tomlString)\n\n if (!workspaceCrn) {\n throw new Error(\n 'You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable.',\n )\n }\n\n return extractWorkspaceIdFromCrn(workspaceCrn)\n}\n","import { initLogger, createRequestLogger } from 'evlog'\nimport type { LoggerConfig } from 'evlog'\n\nexport type LoggingConfig = {\n enabled?: boolean\n pretty?: boolean\n drain?: LoggerConfig['drain']\n}\n\nfunction samplingFromEnv() {\n const env = process.env.STASH_LOG_LEVEL\n if (!env) return undefined\n const levels = ['debug', 'info', 'warn', 'error'] as const\n const idx = levels.indexOf(env as (typeof levels)[number])\n if (idx === -1) return undefined\n return Object.fromEntries(levels.map((l, i) => [l, i >= idx ? 100 : 0]))\n}\n\nlet initialized = false\n\nexport function initStackLogger(config?: LoggingConfig): void {\n if (initialized) return\n initialized = true\n const rates = samplingFromEnv()\n initLogger({\n env: { service: '@cipherstash/stack' },\n enabled: config?.enabled ?? true,\n pretty: config?.pretty,\n ...(rates && { sampling: { rates } }),\n ...(config?.drain && { drain: config.drain }),\n })\n}\n\n// Auto-init with defaults on first import\ninitStackLogger()\n\nexport { createRequestLogger }\n\n// Stringify only the first arg (the message string); drop subsequent args\n// which may contain sensitive objects (e.g. encryptConfig, plaintext).\nfunction safeMessage(args: unknown[]): string {\n return typeof args[0] === 'string' ? args[0] : ''\n}\n\n// Legacy logger for simple one-off logs (used by encryption/ffi/index.ts + identity/index.ts)\nexport const logger = {\n debug(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({ level: 'debug', source: '@cipherstash/stack', message: safeMessage(args) })\n log.emit()\n },\n info(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({ source: '@cipherstash/stack' })\n log.info(safeMessage(args))\n log.emit()\n },\n warn(...args: unknown[]) {\n const log = createRequestLogger()\n log.warn(safeMessage(args))\n log.emit()\n },\n error(...args: unknown[]) {\n const log = createRequestLogger()\n log.error(safeMessage(args))\n log.emit()\n },\n}\n","import { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport {\n type EncryptConfig,\n type ProtectTable,\n type ProtectTableColumn,\n encryptConfigSchema,\n} from '@/schema'\nimport type {\n BulkDecryptPayload,\n BulkEncryptPayload,\n Client,\n Decrypted,\n EncryptOptions,\n EncryptQueryOptions,\n Encrypted,\n KeysetIdentifier,\n ScalarQueryTerm,\n} from '@/types'\nimport { loadWorkSpaceId } from '@/utils/config'\nimport { logger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { type JsPlaintext, newClient } from '@cipherstash/protect-ffi'\nimport { toFfiKeysetIdentifier } from '../helpers'\nimport { isScalarQueryTermArray } from './helpers/type-guards'\nimport { BatchEncryptQueryOperation } from './operations/batch-encrypt-query'\nimport { BulkDecryptOperation } from './operations/bulk-decrypt'\nimport { BulkDecryptModelsOperation } from './operations/bulk-decrypt-models'\nimport { BulkEncryptOperation } from './operations/bulk-encrypt'\nimport { BulkEncryptModelsOperation } from './operations/bulk-encrypt-models'\nimport { DecryptOperation } from './operations/decrypt'\nimport { DecryptModelOperation } from './operations/decrypt-model'\nimport { EncryptOperation } from './operations/encrypt'\nimport { EncryptModelOperation } from './operations/encrypt-model'\nimport { EncryptQueryOperation } from './operations/encrypt-query'\n\nexport const noClientError = () =>\n new Error(\n 'The EQL client has not been initialized. Please call init() before using the client.',\n )\n\n/** The EncryptionClient is the main entry point for interacting with the CipherStash Protect.js library.\n * It provides methods for encrypting and decrypting individual values, as well as models (objects) and bulk operations.\n *\n * The client must be initialized using the {@link Encryption} function before it can be used.\n */\nexport class EncryptionClient {\n private client: Client\n private encryptConfig: EncryptConfig | undefined\n private workspaceId: string | undefined\n\n constructor(workspaceCrn?: string) {\n const workspaceId = loadWorkSpaceId(workspaceCrn)\n this.workspaceId = workspaceId\n }\n\n /**\n * Initializes the EncryptionClient with the provided configuration.\n * @internal\n * @param config - The configuration object for initializing the client.\n * @returns A promise that resolves to a {@link Result} containing the initialized EncryptionClient or an {@link EncryptionError}.\n **/\n async init(config: {\n encryptConfig: EncryptConfig\n workspaceCrn?: string\n accessKey?: string\n clientId?: string\n clientKey?: string\n keyset?: KeysetIdentifier\n }): Promise<Result<EncryptionClient, EncryptionError>> {\n return await withResult(\n async () => {\n const validated: EncryptConfig = encryptConfigSchema.parse(\n config.encryptConfig,\n )\n\n logger.debug(\n 'Initializing the Protect.js client with the following encrypt config:',\n {\n encryptConfig: validated,\n },\n )\n\n this.client = await newClient({\n encryptConfig: validated,\n clientOpts: {\n workspaceCrn: config.workspaceCrn,\n accessKey: config.accessKey,\n clientId: config.clientId,\n clientKey: config.clientKey,\n keyset: toFfiKeysetIdentifier(config.keyset),\n },\n })\n\n this.encryptConfig = validated\n\n logger.debug('Successfully initialized the Protect.js client.')\n return this\n },\n (error: unknown) => ({\n type: EncryptionErrorTypes.ClientInitError,\n message: (error as Error).message,\n }),\n )\n }\n\n /**\n * Encrypt a value - returns a promise which resolves to an encrypted value.\n *\n * @param plaintext - The plaintext value to be encrypted. Can be null.\n * @param opts - Options specifying the column and table for encryption.\n * @returns An EncryptOperation that can be awaited or chained with additional methods.\n *\n * @example\n * The following example demonstrates how to encrypt a value using the Encryption client.\n * It includes defining an encryption schema with {@link encryptedTable} and {@link encryptedColumn},\n * initializing the client with {@link Encryption}, and performing the encryption.\n *\n * `encrypt` returns an {@link EncryptOperation} which can be awaited to get a {@link Result}\n * which can either be the encrypted value or an {@link EncryptionError}.\n *\n * ```typescript\n * // Define encryption schema\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n * const userSchema = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\"),\n * });\n *\n * // Initialize Encryption client\n * const client = await Encryption({ schemas: [userSchema] })\n *\n * // Encrypt a value\n * const encryptedResult = await client.encrypt(\n * \"person@example.com\",\n * { column: userSchema.email, table: userSchema }\n * )\n *\n * // Handle encryption result\n * if (encryptedResult.failure) {\n * throw new Error(`Encryption failed: ${encryptedResult.failure.message}`);\n * }\n *\n * console.log(\"Encrypted data:\", encryptedResult.data);\n * ```\n *\n * @example\n * When encrypting data, a {@link LockContext} can be provided to tie the encryption to a specific user or session.\n * This ensures that the same lock context is required for decryption.\n *\n * The following example demonstrates how to create a lock context using a user's JWT token\n * and use it during encryption.\n *\n * ```typescript\n * // Define encryption schema and initialize client as above\n *\n * // Create a lock for the user's `sub` claim from their JWT\n * const lc = new LockContext();\n * const lockContext = await lc.identify(userJwt);\n *\n * if (lockContext.failure) {\n * // Handle the failure\n * }\n *\n * // Encrypt a value with the lock context\n * // Decryption will then require the same lock context\n * const encryptedResult = await client.encrypt(\n * \"person@example.com\",\n * { column: userSchema.email, table: userSchema }\n * )\n * .withLockContext(lockContext)\n * ```\n *\n * @see {@link Result}\n * @see {@link encryptedTable}\n * @see {@link LockContext}\n * @see {@link EncryptOperation}\n */\n encrypt(\n plaintext: JsPlaintext | null,\n opts: EncryptOptions,\n ): EncryptOperation {\n return new EncryptOperation(this.client, plaintext, opts)\n }\n\n /**\n * Encrypt a query value - returns a promise which resolves to an encrypted query value.\n *\n * @param plaintext - The plaintext value to be encrypted for querying. Can be null.\n * @param opts - Options specifying the column, table, and optional queryType for encryption.\n * @returns An EncryptQueryOperation that can be awaited or chained with additional methods.\n *\n * @example\n * The following example demonstrates how to encrypt a query value using the Encryption client.\n *\n * ```typescript\n * // Define encryption schema\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n * const userSchema = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * });\n *\n * // Initialize Encryption client\n * const client = await Encryption({ schemas: [userSchema] })\n *\n * // Encrypt a query value\n * const encryptedResult = await client.encryptQuery(\n * \"person@example.com\",\n * { column: userSchema.email, table: userSchema, queryType: 'equality' }\n * )\n *\n * // Handle encryption result\n * if (encryptedResult.failure) {\n * throw new Error(`Encryption failed: ${encryptedResult.failure.message}`);\n * }\n *\n * console.log(\"Encrypted query:\", encryptedResult.data);\n * ```\n *\n * @example\n * The queryType can be auto-inferred from the column's configured indexes:\n *\n * ```typescript\n * // When queryType is omitted, it will be inferred from the column's indexes\n * const encryptedResult = await client.encryptQuery(\n * \"person@example.com\",\n * { column: userSchema.email, table: userSchema }\n * )\n * ```\n *\n * @see {@link EncryptQueryOperation}\n *\n * **JSONB columns (searchableJson):**\n * When `queryType` is omitted on a `searchableJson()` column, the query operation is inferred:\n * - String plaintext → `steVecSelector` (JSONPath queries like `'$.user.email'`)\n * - Object/Array plaintext → `steVecTerm` (containment queries like `{ role: 'admin' }`)\n */\n encryptQuery(\n plaintext: JsPlaintext | null,\n opts: EncryptQueryOptions,\n ): EncryptQueryOperation\n\n /**\n * Encrypt multiple values for use in queries (batch operation).\n * @param terms - Array of query terms to encrypt\n */\n encryptQuery(terms: readonly ScalarQueryTerm[]): BatchEncryptQueryOperation\n\n encryptQuery(\n plaintextOrTerms: JsPlaintext | null | readonly ScalarQueryTerm[],\n opts?: EncryptQueryOptions,\n ): EncryptQueryOperation | BatchEncryptQueryOperation {\n // Discriminate between ScalarQueryTerm[] and JsPlaintext (which can also be an array)\n // using a type guard function\n if (isScalarQueryTermArray(plaintextOrTerms)) {\n return new BatchEncryptQueryOperation(this.client, plaintextOrTerms)\n }\n\n // Handle empty arrays: if opts provided, treat as single value; otherwise batch mode\n // This maintains backward compatibility for encryptQuery([]) while allowing\n // encryptQuery([], opts) to encrypt an empty array as a single value\n if (\n Array.isArray(plaintextOrTerms) &&\n plaintextOrTerms.length === 0 &&\n !opts\n ) {\n return new BatchEncryptQueryOperation(\n this.client,\n [] as readonly ScalarQueryTerm[],\n )\n }\n\n if (!opts) {\n throw new Error('EncryptQueryOptions are required')\n }\n\n return new EncryptQueryOperation(\n this.client,\n plaintextOrTerms as JsPlaintext | null,\n opts,\n )\n }\n\n /**\n * Decryption - returns a promise which resolves to a decrypted value.\n *\n * @param encryptedData - The encrypted data to be decrypted.\n * @returns A DecryptOperation that can be awaited or chained with additional methods.\n *\n * @example\n * The following example demonstrates how to decrypt a value that was previously encrypted using the {@link encrypt} method.\n * It includes encrypting a value first, then decrypting it, and handling the result.\n *\n * ```typescript\n * const encryptedData = await client.encrypt(\n * \"person@example.com\",\n * { column: \"email\", table: \"users\" }\n * )\n * const decryptResult = await client.decrypt(encryptedData)\n * if (decryptResult.failure) {\n * throw new Error(`Decryption failed: ${decryptResult.failure.message}`);\n * }\n * console.log(\"Decrypted data:\", decryptResult.data);\n * ```\n *\n * @example\n * Provide a lock context when decrypting:\n * ```typescript\n * await client.decrypt(encryptedData)\n * .withLockContext(lockContext)\n * ```\n *\n * @see {@link LockContext}\n * @see {@link DecryptOperation}\n */\n decrypt(encryptedData: Encrypted): DecryptOperation {\n return new DecryptOperation(this.client, encryptedData)\n }\n\n /**\n * Encrypt a model (object) based on the table schema.\n *\n * Only fields whose keys match columns defined in the table schema are encrypted.\n * All other fields are passed through unchanged. Returns a thenable operation\n * that supports `.withLockContext()` for identity-aware encryption.\n *\n * @param input - The model object with plaintext values to encrypt.\n * @param table - The table schema defining which fields to encrypt.\n * @returns An `EncryptModelOperation<T>` that can be awaited to get a `Result`\n * containing the model with encrypted fields, or an `EncryptionError`.\n *\n * @example\n * ```typescript\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * type User = { id: string; email: string; createdAt: Date }\n *\n * const usersSchema = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const client = await Encryption({ schemas: [usersSchema] })\n *\n * const result = await client.encryptModel<User>(\n * { id: \"user_123\", email: \"alice@example.com\", createdAt: new Date() },\n * usersSchema,\n * )\n *\n * if (result.failure) {\n * console.error(result.failure.message)\n * } else {\n * // result.data.id is unchanged, result.data.email is encrypted\n * console.log(result.data)\n * }\n * ```\n */\n encryptModel<T extends Record<string, unknown>>(\n input: Decrypted<T>,\n table: ProtectTable<ProtectTableColumn>,\n ): EncryptModelOperation<T> {\n return new EncryptModelOperation(this.client, input, table)\n }\n\n /**\n * Decrypt a model (object) whose fields contain encrypted values.\n *\n * Identifies encrypted fields automatically and decrypts them, returning the\n * model with plaintext values. Returns a thenable operation that supports\n * `.withLockContext()` for identity-aware decryption.\n *\n * @param input - The model object with encrypted field values.\n * @returns A `DecryptModelOperation<T>` that can be awaited to get a `Result`\n * containing the model with decrypted plaintext fields, or an `EncryptionError`.\n *\n * @example\n * ```typescript\n * // Decrypt a previously encrypted model\n * const decrypted = await client.decryptModel<User>(encryptedUser)\n *\n * if (decrypted.failure) {\n * console.error(decrypted.failure.message)\n * } else {\n * console.log(decrypted.data.email) // \"alice@example.com\"\n * }\n *\n * // With a lock context\n * const decrypted = await client\n * .decryptModel<User>(encryptedUser)\n * .withLockContext(lockContext)\n * ```\n */\n decryptModel<T extends Record<string, unknown>>(\n input: T,\n ): DecryptModelOperation<T> {\n return new DecryptModelOperation(this.client, input)\n }\n\n /**\n * Encrypt multiple models (objects) in a single bulk operation.\n *\n * Performs a single call to ZeroKMS regardless of the number of models,\n * while still using a unique key for each encrypted value. Only fields\n * matching the table schema are encrypted; other fields pass through unchanged.\n *\n * @param input - An array of model objects with plaintext values to encrypt.\n * @param table - The table schema defining which fields to encrypt.\n * @returns A `BulkEncryptModelsOperation<T>` that can be awaited to get a `Result`\n * containing an array of models with encrypted fields, or an `EncryptionError`.\n *\n * @example\n * ```typescript\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * type User = { id: string; email: string }\n *\n * const usersSchema = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\"),\n * })\n *\n * const client = await Encryption({ schemas: [usersSchema] })\n *\n * const result = await client.bulkEncryptModels<User>(\n * [\n * { id: \"1\", email: \"alice@example.com\" },\n * { id: \"2\", email: \"bob@example.com\" },\n * ],\n * usersSchema,\n * )\n *\n * if (!result.failure) {\n * console.log(result.data) // array of models with encrypted email fields\n * }\n * ```\n */\n bulkEncryptModels<T extends Record<string, unknown>>(\n input: Array<Decrypted<T>>,\n table: ProtectTable<ProtectTableColumn>,\n ): BulkEncryptModelsOperation<T> {\n return new BulkEncryptModelsOperation(this.client, input, table)\n }\n\n /**\n * Decrypt multiple models (objects) in a single bulk operation.\n *\n * Performs a single call to ZeroKMS regardless of the number of models,\n * restoring all encrypted fields to their original plaintext values.\n *\n * @param input - An array of model objects with encrypted field values.\n * @returns A `BulkDecryptModelsOperation<T>` that can be awaited to get a `Result`\n * containing an array of models with decrypted plaintext fields, or an `EncryptionError`.\n *\n * @example\n * ```typescript\n * const encryptedUsers = encryptedResult.data // from bulkEncryptModels\n *\n * const result = await client.bulkDecryptModels<User>(encryptedUsers)\n *\n * if (!result.failure) {\n * for (const user of result.data) {\n * console.log(user.email) // plaintext email\n * }\n * }\n *\n * // With a lock context\n * const result = await client\n * .bulkDecryptModels<User>(encryptedUsers)\n * .withLockContext(lockContext)\n * ```\n */\n bulkDecryptModels<T extends Record<string, unknown>>(\n input: Array<T>,\n ): BulkDecryptModelsOperation<T> {\n return new BulkDecryptModelsOperation(this.client, input)\n }\n\n /**\n * Encrypt multiple plaintext values in a single bulk operation.\n *\n * Each value is encrypted with its own unique key via a single call to ZeroKMS.\n * Values can include optional `id` fields for correlating results back to\n * your application data. Null plaintext values are preserved as null.\n *\n * @param plaintexts - An array of objects with `plaintext` (and optional `id`) fields.\n * @param opts - Options specifying the target column and table for encryption.\n * @returns A `BulkEncryptOperation` that can be awaited to get a `Result`\n * containing an array of `{ id?, data: Encrypted }` objects, or an `EncryptionError`.\n *\n * @example\n * ```typescript\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\"),\n * })\n * const client = await Encryption({ schemas: [users] })\n *\n * const result = await client.bulkEncrypt(\n * [\n * { id: \"u1\", plaintext: \"alice@example.com\" },\n * { id: \"u2\", plaintext: \"bob@example.com\" },\n * { id: \"u3\", plaintext: null },\n * ],\n * { column: users.email, table: users },\n * )\n *\n * if (!result.failure) {\n * // result.data = [{ id: \"u1\", data: Encrypted }, { id: \"u2\", data: Encrypted }, ...]\n * console.log(result.data)\n * }\n * ```\n */\n bulkEncrypt(\n plaintexts: BulkEncryptPayload,\n opts: EncryptOptions,\n ): BulkEncryptOperation {\n return new BulkEncryptOperation(this.client, plaintexts, opts)\n }\n\n /**\n * Decrypt multiple encrypted values in a single bulk operation.\n *\n * Performs a single call to ZeroKMS to decrypt all values. The result uses\n * a multi-status pattern: each item in the returned array has either a `data`\n * field (success) or an `error` field (failure), allowing graceful handling\n * of partial failures.\n *\n * @param encryptedPayloads - An array of objects with `data` (encrypted payload) and optional `id` fields.\n * @returns A `BulkDecryptOperation` that can be awaited to get a `Result`\n * containing an array of `{ id?, data: plaintext }` or `{ id?, error: string }` objects,\n * or an `EncryptionError` if the entire operation fails.\n *\n * @example\n * ```typescript\n * const encrypted = await client.bulkEncrypt(plaintexts, { column: users.email, table: users })\n *\n * const result = await client.bulkDecrypt(encrypted.data)\n *\n * if (!result.failure) {\n * for (const item of result.data) {\n * if (\"data\" in item) {\n * console.log(`${item.id}: ${item.data}`)\n * } else {\n * console.error(`${item.id} failed: ${item.error}`)\n * }\n * }\n * }\n * ```\n */\n bulkDecrypt(encryptedPayloads: BulkDecryptPayload): BulkDecryptOperation {\n return new BulkDecryptOperation(this.client, encryptedPayloads)\n }\n\n /** e.g., debugging or environment info */\n clientInfo() {\n return {\n workspaceId: this.workspaceId,\n }\n }\n}\n","import type { ScalarQueryTerm } from '../../../types'\n\n/**\n * Type guard to check if a value is an array of ScalarQueryTerm objects.\n * Used to discriminate between single value and bulk encryption in encryptQuery overloads.\n */\nexport function isScalarQueryTermArray(\n value: unknown,\n): value is readonly ScalarQueryTerm[] {\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n typeof value[0] === 'object' &&\n value[0] !== null &&\n 'column' in value[0] &&\n 'table' in value[0]\n )\n}\n","import {\n ProtectError as FfiProtectError,\n type ProtectErrorCode,\n} from '@cipherstash/protect-ffi'\n\n/**\n * Extracts FFI error code from an error if it's an FFI error, otherwise returns undefined.\n * Used to preserve specific error codes in ProtectError responses.\n */\nexport function getErrorCode(error: unknown): ProtectErrorCode | undefined {\n return error instanceof FfiProtectError ? error.code : undefined\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { formatEncryptedResult } from '@/encryption/helpers'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { Context, LockContext } from '@/identity'\nimport type { Client, EncryptedQueryResult, ScalarQueryTerm } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport {\n type JsPlaintext,\n type QueryPayload,\n encryptQueryBulk as ffiEncryptQueryBulk,\n} from '@cipherstash/protect-ffi'\nimport type { Encrypted as CipherStashEncrypted } from '@cipherstash/protect-ffi'\nimport { resolveIndexType } from '../helpers/infer-index-type'\nimport {\n assertValidNumericValue,\n assertValueIndexCompatibility,\n} from '../helpers/validation'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n/**\n * Separates null/undefined values from non-null terms in the input array.\n * Returns a set of indices where values are null/undefined and an array of non-null terms with their original indices.\n */\nfunction filterNullTerms(terms: readonly ScalarQueryTerm[]): {\n nullIndices: Set<number>\n nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[]\n} {\n const nullIndices = new Set<number>()\n const nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[] = []\n\n terms.forEach((term, index) => {\n if (term.value === null || term.value === undefined) {\n nullIndices.add(index)\n } else {\n nonNullTerms.push({ term, originalIndex: index })\n }\n })\n\n return { nullIndices, nonNullTerms }\n}\n\n/**\n * Validates and transforms a single term into a QueryPayload.\n * Throws an error if the value is NaN or Infinity.\n * Optionally includes lockContext if provided.\n */\nfunction buildQueryPayload(\n term: ScalarQueryTerm,\n lockContext?: Context,\n): QueryPayload {\n assertValidNumericValue(term.value)\n\n const { indexType, queryOp } = resolveIndexType(\n term.column,\n term.queryType,\n term.value,\n )\n\n // Validate value/index compatibility\n assertValueIndexCompatibility(term.value, indexType, term.column.getName())\n\n const payload: QueryPayload = {\n plaintext: term.value as JsPlaintext,\n column: term.column.getName(),\n table: term.table.tableName,\n indexType,\n queryOp,\n }\n\n if (lockContext != null) {\n payload.lockContext = lockContext\n }\n\n return payload\n}\n\n/**\n * Reconstructs the results array with nulls in their original positions.\n * Non-null encrypted values are placed at their original indices.\n * Applies formatting based on term.returnType.\n */\nfunction assembleResults(\n totalLength: number,\n encryptedValues: CipherStashEncrypted[],\n nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[],\n): EncryptedQueryResult[] {\n const results: EncryptedQueryResult[] = new Array(totalLength).fill(null)\n\n // Fill in encrypted values at their original positions, applying formatting\n nonNullTerms.forEach(({ term, originalIndex }, i) => {\n const encrypted = encryptedValues[i]\n\n results[originalIndex] = formatEncryptedResult(encrypted, term.returnType)\n })\n\n return results\n}\n\n/**\n * @internal Use {@link EncryptionClient.encryptQuery} with array input instead.\n */\nexport class BatchEncryptQueryOperation extends EncryptionOperation<\n EncryptedQueryResult[]\n> {\n constructor(\n private client: Client,\n private terms: readonly ScalarQueryTerm[],\n ) {\n super()\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): BatchEncryptQueryOperationWithLockContext {\n return new BatchEncryptQueryOperationWithLockContext(\n this.client,\n this.terms,\n lockContext,\n this.auditMetadata,\n )\n }\n\n public async execute(): Promise<\n Result<EncryptedQueryResult[], EncryptionError>\n > {\n const log = createRequestLogger()\n log.set({\n op: 'batchEncryptQuery',\n count: this.terms.length,\n lockContext: false,\n })\n\n if (this.terms.length === 0) {\n log.emit()\n return { data: [] }\n }\n\n const { nullIndices, nonNullTerms } = filterNullTerms(this.terms)\n\n if (nonNullTerms.length === 0) {\n log.emit()\n return { data: this.terms.map(() => null) }\n }\n\n const result = await withResult(\n async () => {\n if (!this.client) throw noClientError()\n\n const { metadata } = this.getAuditData()\n\n const queries: QueryPayload[] = nonNullTerms.map(({ term }) =>\n buildQueryPayload(term),\n )\n\n const encrypted = await ffiEncryptQueryBulk(this.client, {\n queries,\n unverifiedContext: metadata,\n })\n\n return assembleResults(this.terms.length, encrypted, nonNullTerms)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n\n/**\n * @internal Use {@link EncryptionClient.encryptQuery} with array input and `.withLockContext()` instead.\n */\nexport class BatchEncryptQueryOperationWithLockContext extends EncryptionOperation<\n EncryptedQueryResult[]\n> {\n constructor(\n private client: Client,\n private terms: readonly ScalarQueryTerm[],\n private lockContext: LockContext,\n auditMetadata?: Record<string, unknown>,\n ) {\n super()\n this.auditMetadata = auditMetadata\n }\n\n public async execute(): Promise<\n Result<EncryptedQueryResult[], EncryptionError>\n > {\n const log = createRequestLogger()\n log.set({\n op: 'batchEncryptQuery',\n count: this.terms.length,\n lockContext: true,\n })\n\n if (this.terms.length === 0) {\n log.emit()\n return { data: [] }\n }\n\n // Check for all-null terms BEFORE fetching lockContext to avoid unnecessary network call\n const { nullIndices, nonNullTerms } = filterNullTerms(this.terms)\n\n if (nonNullTerms.length === 0) {\n log.emit()\n return { data: this.terms.map(() => null) }\n }\n\n const lockContextResult = await this.lockContext.getLockContext()\n if (lockContextResult.failure) {\n log.emit()\n return { failure: lockContextResult.failure }\n }\n\n const { ctsToken, context } = lockContextResult.data\n\n const result = await withResult(\n async () => {\n if (!this.client) throw noClientError()\n\n const { metadata } = this.getAuditData()\n\n const queries: QueryPayload[] = nonNullTerms.map(({ term }) =>\n buildQueryPayload(term, context),\n )\n\n const encrypted = await ffiEncryptQueryBulk(this.client, {\n queries,\n serviceToken: ctsToken,\n unverifiedContext: metadata,\n })\n\n return assembleResults(this.terms.length, encrypted, nonNullTerms)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import type {\n ProtectColumn,\n ProtectTable,\n ProtectTableColumn,\n ProtectValue,\n} from '@/schema'\nimport type { LoggingConfig } from '@/utils/logger'\nimport type {\n Encrypted as CipherStashEncrypted,\n JsPlaintext,\n QueryOpName,\n newClient,\n} from '@cipherstash/protect-ffi'\n\n// ---------------------------------------------------------------------------\n// Branded type utilities\n// ---------------------------------------------------------------------------\n\n/** Brand symbol for nominal typing */\ndeclare const __brand: unique symbol\n\n/** Creates a branded type that is structurally incompatible with the base type */\ntype Brand<T, B extends string> = T & { readonly [__brand]: B }\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\nexport type Client = Awaited<ReturnType<typeof newClient>> | undefined\n\n/** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */\nexport type EncryptedValue = Brand<CipherStashEncrypted, 'encrypted'> | null\n\n/** Structural type representing encrypted data. See also `EncryptedValue` for branded nominal typing. */\nexport type Encrypted = CipherStashEncrypted | null\n\nexport type EncryptPayload = JsPlaintext | null\n\n// ---------------------------------------------------------------------------\n// Client configuration\n// ---------------------------------------------------------------------------\n\nexport type KeysetIdentifier = { name: string } | { id: string }\n\nexport type ClientConfig = {\n /**\n * The CipherStash workspace CRN (Cloud Resource Name).\n * Format: `crn:<region>.aws:<workspace-id>`.\n * Can also be set via the `CS_WORKSPACE_CRN` environment variable.\n * If omitted, the SDK reads from the environment or TOML config files.\n */\n workspaceCrn?: string\n\n /**\n * The API access key used for authenticating with the CipherStash API.\n * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.\n * Obtain this from the CipherStash dashboard after creating a workspace.\n */\n accessKey?: string\n\n /**\n * The client identifier used to authenticate with CipherStash services.\n * Can also be set via the `CS_CLIENT_ID` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientId?: string\n\n /**\n * The client key material used in combination with ZeroKMS for encryption operations.\n * Can also be set via the `CS_CLIENT_KEY` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientKey?: string\n\n /**\n * An optional keyset identifier for multi-tenant encryption.\n * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.\n * Specify by name (`{ name: \"tenant-a\" }`) or UUID (`{ id: \"...\" }`).\n * Keysets are created and managed in the CipherStash dashboard.\n */\n keyset?: KeysetIdentifier\n}\n\ntype AtLeastOneCsTable<T> = [T, ...T[]]\n\nexport type EncryptionClientConfig = {\n schemas: AtLeastOneCsTable<ProtectTable<ProtectTableColumn>>\n config?: ClientConfig\n logging?: LoggingConfig\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt operation options and results\n// ---------------------------------------------------------------------------\n\nexport type EncryptOptions = {\n column: ProtectColumn | ProtectValue\n table: ProtectTable<ProtectTableColumn>\n}\n\n/** Format for encrypted query/search term return values */\nexport type EncryptedReturnType =\n | 'eql'\n | 'composite-literal'\n | 'escaped-composite-literal'\n\nexport type SearchTerm = {\n value: JsPlaintext\n column: ProtectColumn\n table: ProtectTable<ProtectTableColumn>\n returnType?: EncryptedReturnType\n}\n\n/** Encrypted search term result: EQL object or composite literal string */\nexport type EncryptedSearchTerm = Encrypted | string\n\n/** Result of encryptQuery (single or batch): EQL, composite literal string, or null */\nexport type EncryptedQueryResult = Encrypted | string | null\n\n// ---------------------------------------------------------------------------\n// Model field types (encrypted vs decrypted views)\n// ---------------------------------------------------------------------------\n\nexport type EncryptedFields<T> = {\n [K in keyof T as T[K] extends Encrypted ? K : never]: T[K]\n}\n\nexport type OtherFields<T> = {\n [K in keyof T as T[K] extends Encrypted ? never : K]: T[K]\n}\n\nexport type DecryptedFields<T> = {\n [K in keyof T as T[K] extends Encrypted ? K : never]: string\n}\n\n/** Model with encrypted fields replaced by plaintext (decrypted) values */\nexport type Decrypted<T> = OtherFields<T> & DecryptedFields<T>\n\n// ---------------------------------------------------------------------------\n// Bulk operations\n// ---------------------------------------------------------------------------\n\nexport type BulkEncryptPayload = Array<{\n id?: string\n plaintext: JsPlaintext | null\n}>\n\nexport type BulkEncryptedData = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptPayload = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptedData = Array<DecryptionResult<JsPlaintext | null>>\n\ntype DecryptionSuccess<T> = { error?: never; data: T; id?: string }\ntype DecryptionError<T> = { error: T; id?: string; data?: never }\n\n/**\n * Result type for individual items in bulk decrypt operations.\n * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations\n * can have per-item failures.\n */\nexport type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>\n\n// ---------------------------------------------------------------------------\n// Query types (for searchable encryption / encryptQuery)\n// ---------------------------------------------------------------------------\n\n/**\n * User-facing query type names for encrypting query values.\n *\n * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/exact)\n * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/match)\n * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/range)\n * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)\n * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)\n * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)\n */\nexport type QueryTypeName =\n | 'orderAndRange'\n | 'freeTextSearch'\n | 'equality'\n | 'steVecSelector'\n | 'steVecTerm'\n | 'searchableJson'\n\n/** @internal */\nexport type FfiIndexTypeName = 'ore' | 'match' | 'unique' | 'ste_vec'\n\nexport const queryTypes = {\n orderAndRange: 'orderAndRange',\n freeTextSearch: 'freeTextSearch',\n equality: 'equality',\n steVecSelector: 'steVecSelector',\n steVecTerm: 'steVecTerm',\n searchableJson: 'searchableJson',\n} as const satisfies Record<string, QueryTypeName>\n\n/** @internal */\nexport const queryTypeToFfi: Record<QueryTypeName, FfiIndexTypeName> = {\n orderAndRange: 'ore',\n freeTextSearch: 'match',\n equality: 'unique',\n steVecSelector: 'ste_vec',\n steVecTerm: 'ste_vec',\n searchableJson: 'ste_vec',\n}\n\n/** @internal */\nexport const queryTypeToQueryOp: Partial<Record<QueryTypeName, QueryOpName>> = {\n steVecSelector: 'ste_vec_selector',\n steVecTerm: 'ste_vec_term',\n}\n\n/** @internal */\nexport type QueryTermBase = {\n column: ProtectColumn\n table: ProtectTable<ProtectTableColumn>\n queryType?: QueryTypeName\n returnType?: EncryptedReturnType\n}\n\nexport type EncryptQueryOptions = QueryTermBase\n\nexport type ScalarQueryTerm = QueryTermBase & {\n value: JsPlaintext | null\n}\n","import type { ProtectColumn } from '@/schema'\nimport type { JsPlaintext, QueryOpName } from '@cipherstash/protect-ffi'\nimport type { FfiIndexTypeName, QueryTypeName } from '../../../types'\nimport { queryTypeToFfi, queryTypeToQueryOp } from '../../../types'\n\n/**\n * Infer the primary index type from a column's configured indexes.\n * Priority: unique > match > ore > ste_vec (for scalar queries)\n */\nexport function inferIndexType(column: ProtectColumn): FfiIndexTypeName {\n const config = column.build()\n const indexes = config.indexes\n\n if (!indexes || Object.keys(indexes).length === 0) {\n throw new Error(`Column \"${column.getName()}\" has no indexes configured`)\n }\n\n // Priority order for inference\n if (indexes.unique) return 'unique'\n if (indexes.match) return 'match'\n if (indexes.ore) return 'ore'\n if (indexes.ste_vec) return 'ste_vec'\n\n throw new Error(\n `Column \"${column.getName()}\" has no suitable index for queries`,\n )\n}\n\n/**\n * Infer the FFI query operation from plaintext type for STE Vec queries.\n * - String → ste_vec_selector (JSONPath queries like '$.user.email')\n * - Object/Array/Number/Boolean → ste_vec_term (containment queries)\n */\nexport function inferQueryOpFromPlaintext(plaintext: JsPlaintext): QueryOpName {\n if (typeof plaintext === 'string') {\n return 'ste_vec_selector'\n }\n // Objects, arrays, numbers, booleans are all valid JSONB containment values\n if (\n typeof plaintext === 'object' ||\n typeof plaintext === 'number' ||\n typeof plaintext === 'boolean' ||\n typeof plaintext === 'bigint'\n ) {\n return 'ste_vec_term'\n }\n // This should never happen with valid JsPlaintext, but keep for safety\n return 'ste_vec_term'\n}\n\n/**\n * Validate that the specified index type is configured on the column\n */\nexport function validateIndexType(\n column: ProtectColumn,\n indexType: FfiIndexTypeName,\n): void {\n const config = column.build()\n const indexes = config.indexes ?? {}\n\n const indexMap: Record<string, boolean> = {\n unique: !!indexes.unique,\n match: !!indexes.match,\n ore: !!indexes.ore,\n ste_vec: !!indexes.ste_vec,\n }\n\n if (!indexMap[indexType]) {\n throw new Error(\n `Index type \"${indexType}\" is not configured on column \"${column.getName()}\"`,\n )\n }\n}\n\n/**\n * Resolve the index type and query operation for a query.\n * Validates the index type is configured on the column when queryType is explicit.\n * For ste_vec columns without explicit queryType, infers queryOp from plaintext shape.\n *\n * @param column - The column to resolve the index type for\n * @param queryType - Optional explicit query type (if provided, validates against column config)\n * @param plaintext - Optional plaintext value for queryOp inference on ste_vec columns\n * @returns The FFI index type name and optional query operation name\n * @throws Error if ste_vec is inferred but queryOp cannot be determined\n */\nexport function resolveIndexType(\n column: ProtectColumn,\n queryType?: QueryTypeName,\n plaintext?: JsPlaintext | null,\n): { indexType: FfiIndexTypeName; queryOp?: QueryOpName } {\n const indexType = queryType\n ? queryTypeToFfi[queryType]\n : inferIndexType(column)\n\n if (queryType) {\n validateIndexType(column, indexType)\n\n // For searchableJson, infer queryOp from plaintext type (not from mapping)\n if (queryType === 'searchableJson') {\n if (plaintext === undefined || plaintext === null) {\n return { indexType }\n }\n return { indexType, queryOp: inferQueryOpFromPlaintext(plaintext) }\n }\n\n return { indexType, queryOp: queryTypeToQueryOp[queryType] }\n }\n\n // ste_vec inferred without explicit queryType → must infer from plaintext\n if (indexType === 'ste_vec') {\n if (plaintext === undefined || plaintext === null) {\n // Null plaintext handled by caller (returns null early) - no inference needed\n return { indexType }\n }\n return { indexType, queryOp: inferQueryOpFromPlaintext(plaintext) }\n }\n\n // Non-ste_vec → no queryOp needed\n return { indexType }\n}\n","import { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { FfiIndexTypeName } from '@/types'\nimport type { Result } from '@byteslice/result'\n\n/**\n * Validates that a value is not NaN or Infinity.\n * Returns a failure Result if validation fails, undefined otherwise.\n * Use this in async flows that return Result types.\n *\n * Uses `never` as the success type so the result can be assigned to any Result<T, EncryptionError>.\n *\n * @internal\n */\nexport function validateNumericValue(\n value: unknown,\n): Result<never, EncryptionError> | undefined {\n if (typeof value === 'number' && Number.isNaN(value)) {\n return {\n failure: {\n type: EncryptionErrorTypes.EncryptionError,\n message: '[encryption]: Cannot encrypt NaN value',\n },\n }\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n return {\n failure: {\n type: EncryptionErrorTypes.EncryptionError,\n message: '[encryption]: Cannot encrypt Infinity value',\n },\n }\n }\n return undefined\n}\n\n/**\n * Validates that a value is not NaN or Infinity.\n * Throws an error if validation fails.\n * Use this in sync flows where exceptions are caught.\n *\n * @internal\n */\nexport function assertValidNumericValue(value: unknown): void {\n if (typeof value === 'number' && Number.isNaN(value)) {\n throw new Error('[encryption]: Cannot encrypt NaN value')\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw new Error('[encryption]: Cannot encrypt Infinity value')\n }\n}\n\n/**\n * Validates that the value type is compatible with the index type.\n * Match index (freeTextSearch) only supports string values.\n * Returns a failure Result if validation fails, undefined otherwise.\n * Use this in async flows that return Result types.\n *\n * @internal\n */\nexport function validateValueIndexCompatibility(\n value: unknown,\n indexType: FfiIndexTypeName,\n columnName: string,\n): Result<never, EncryptionError> | undefined {\n if (typeof value === 'number' && indexType === 'match') {\n return {\n failure: {\n type: EncryptionErrorTypes.EncryptionError,\n message: `[encryption]: Cannot use 'match' index with numeric value on column \"${columnName}\". The 'freeTextSearch' index only supports string values. Configure the column with 'orderAndRange()' or 'equality()' for numeric queries.`,\n },\n }\n }\n return undefined\n}\n\n/**\n * Validates that the value type is compatible with the index type.\n * Match index (freeTextSearch) only supports string values.\n * Throws an error if validation fails.\n * Use this in sync flows where exceptions are caught.\n *\n * @internal\n */\nexport function assertValueIndexCompatibility(\n value: unknown,\n indexType: FfiIndexTypeName,\n columnName: string,\n): void {\n if (typeof value === 'number' && indexType === 'match') {\n throw new Error(\n `[encryption]: Cannot use 'match' index with numeric value on column \"${columnName}\". The 'freeTextSearch' index only supports string values. Configure the column with 'orderAndRange()' or 'equality()' for numeric queries.`,\n )\n }\n}\n","import type { EncryptionError } from '@/errors'\nimport type { Result } from '@byteslice/result'\n\nexport type AuditConfig = {\n metadata?: Record<string, unknown>\n}\n\nexport type AuditData = {\n metadata?: Record<string, unknown>\n}\n\nexport abstract class EncryptionOperation<T> {\n protected auditMetadata?: Record<string, unknown>\n\n /**\n * Attach audit metadata to this operation. Can be chained.\n * @param config Configuration for ZeroKMS audit logging\n * @param config.metadata Arbitrary JSON object for appending metadata to the audit log\n */\n audit(config: AuditConfig): this {\n this.auditMetadata = config.metadata\n return this\n }\n\n /**\n * Get the audit data for this operation.\n */\n public getAuditData(): AuditData {\n return {\n metadata: this.auditMetadata,\n }\n }\n\n /**\n * Execute the operation and return a Result\n */\n abstract execute(): Promise<Result<T, EncryptionError>>\n\n /**\n * Make the operation thenable\n */\n public then<TResult1 = Result<T, EncryptionError>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Result<T, EncryptionError>,\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","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { Context, LockContext } from '@/identity'\nimport type { BulkDecryptPayload, BulkDecryptedData, Client } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport {\n type Encrypted as CipherStashEncrypted,\n type DecryptResult,\n decryptBulkFallible,\n} from '@cipherstash/protect-ffi'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n// Helper functions for better composability\nconst createDecryptPayloads = (\n encryptedPayloads: BulkDecryptPayload,\n lockContext?: Context,\n) => {\n return encryptedPayloads\n .map((item, index) => ({ ...item, originalIndex: index }))\n .filter(({ data }) => data !== null)\n .map(({ id, data, originalIndex }) => ({\n id,\n ciphertext: data as CipherStashEncrypted,\n originalIndex,\n ...(lockContext && { lockContext }),\n }))\n}\n\nconst createNullResult = (\n encryptedPayloads: BulkDecryptPayload,\n): BulkDecryptedData => {\n return encryptedPayloads.map(({ id }) => ({\n id,\n data: null,\n }))\n}\n\nconst mapDecryptedDataToResult = (\n encryptedPayloads: BulkDecryptPayload,\n decryptedData: DecryptResult[],\n): BulkDecryptedData => {\n const result: BulkDecryptedData = new Array(encryptedPayloads.length)\n let decryptedIndex = 0\n\n for (let i = 0; i < encryptedPayloads.length; i++) {\n if (encryptedPayloads[i].data === null) {\n result[i] = { id: encryptedPayloads[i].id, data: null }\n } else {\n const decryptResult = decryptedData[decryptedIndex]\n if ('error' in decryptResult) {\n result[i] = {\n id: encryptedPayloads[i].id,\n error: decryptResult.error,\n }\n } else {\n result[i] = {\n id: encryptedPayloads[i].id,\n data: decryptResult.data,\n }\n }\n decryptedIndex++\n }\n }\n\n return result\n}\n\nexport class BulkDecryptOperation extends EncryptionOperation<BulkDecryptedData> {\n private client: Client\n private encryptedPayloads: BulkDecryptPayload\n\n constructor(client: Client, encryptedPayloads: BulkDecryptPayload) {\n super()\n this.client = client\n this.encryptedPayloads = encryptedPayloads\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): BulkDecryptOperationWithLockContext {\n return new BulkDecryptOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<BulkDecryptedData, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'bulkDecrypt',\n count: this.encryptedPayloads?.length ?? 0,\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) throw noClientError()\n if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)\n return []\n\n const nonNullPayloads = createDecryptPayloads(this.encryptedPayloads)\n\n if (nonNullPayloads.length === 0) {\n return createNullResult(this.encryptedPayloads)\n }\n\n const { metadata } = this.getAuditData()\n\n const decryptedData = await decryptBulkFallible(this.client, {\n ciphertexts: nonNullPayloads,\n unverifiedContext: metadata,\n })\n\n return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n encryptedPayloads: BulkDecryptPayload\n } {\n return {\n client: this.client,\n encryptedPayloads: this.encryptedPayloads,\n }\n }\n}\n\nexport class BulkDecryptOperationWithLockContext extends EncryptionOperation<BulkDecryptedData> {\n private operation: BulkDecryptOperation\n private lockContext: LockContext\n\n constructor(operation: BulkDecryptOperation, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<BulkDecryptedData, EncryptionError>> {\n const { client, encryptedPayloads } = this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'bulkDecrypt',\n count: encryptedPayloads?.length ?? 0,\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) throw noClientError()\n if (!encryptedPayloads || encryptedPayloads.length === 0) return []\n\n const context = await this.lockContext.getLockContext()\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const nonNullPayloads = createDecryptPayloads(\n encryptedPayloads,\n context.data.context,\n )\n\n if (nonNullPayloads.length === 0) {\n return createNullResult(encryptedPayloads)\n }\n\n const { metadata } = this.getAuditData()\n\n const decryptedData = await decryptBulkFallible(client, {\n ciphertexts: nonNullPayloads,\n serviceToken: context.data.ctsToken,\n unverifiedContext: metadata,\n })\n\n return mapDecryptedDataToResult(encryptedPayloads, decryptedData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { noClientError } from '../index'\nimport {\n bulkDecryptModels,\n bulkDecryptModelsWithLockContext,\n} from '../model-helpers'\nimport { EncryptionOperation } from './base-operation'\n\nexport class BulkDecryptModelsOperation<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<Decrypted<T>[]> {\n private client: Client\n private models: T[]\n\n constructor(client: Client, models: T[]) {\n super()\n this.client = client\n this.models = models\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): BulkDecryptModelsOperationWithLockContext<T> {\n return new BulkDecryptModelsOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<Decrypted<T>[], EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'bulkDecryptModels',\n count: this.models.length,\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n const auditData = this.getAuditData()\n\n return await bulkDecryptModels<T>(this.models, this.client, auditData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n models: T[]\n } {\n return {\n client: this.client,\n models: this.models,\n }\n }\n}\n\nexport class BulkDecryptModelsOperationWithLockContext<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<Decrypted<T>[]> {\n private operation: BulkDecryptModelsOperation<T>\n private lockContext: LockContext\n\n constructor(\n operation: BulkDecryptModelsOperation<T>,\n lockContext: LockContext,\n ) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<Decrypted<T>[], EncryptionError>> {\n const { client, models } = this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'bulkDecryptModels',\n count: models.length,\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) {\n throw noClientError()\n }\n\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const auditData = this.getAuditData()\n\n return await bulkDecryptModelsWithLockContext<T>(\n models,\n client,\n context.data,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import type { AuditData } from '@/encryption/ffi/operations/base-operation'\nimport { isEncryptedPayload } from '@/encryption/helpers'\nimport type { GetLockContextResponse } from '@/identity'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { Client, Decrypted, Encrypted } from '@/types'\nimport {\n type Encrypted as CipherStashEncrypted,\n decryptBulk,\n encryptBulk,\n} from '@cipherstash/protect-ffi'\n\n/**\n * Sets a value at a nested path in an object, creating intermediate objects as needed.\n * Includes prototype pollution protection.\n */\nfunction setNestedValue(\n obj: Record<string, unknown>,\n path: string[],\n value: unknown,\n): void {\n const FORBIDDEN_KEYS = ['__proto__', 'prototype', 'constructor']\n let current: Record<string, unknown> = obj\n for (let i = 0; i < path.length - 1; i++) {\n const part = path[i]\n if (FORBIDDEN_KEYS.includes(part)) {\n throw new Error(`[encryption]: Forbidden key \"${part}\" in field path`)\n }\n if (\n !(part in current) ||\n typeof current[part] !== 'object' ||\n current[part] === null\n ) {\n current[part] = {}\n }\n current = current[part] as Record<string, unknown>\n }\n const lastKey = path[path.length - 1]\n if (FORBIDDEN_KEYS.includes(lastKey)) {\n throw new Error(`[encryption]: Forbidden key \"${lastKey}\" in field path`)\n }\n current[lastKey] = value\n}\n\n/**\n * Helper function to extract encrypted fields from a model\n */\nexport function extractEncryptedFields<T extends Record<string, unknown>>(\n model: T,\n): Record<string, Encrypted> {\n const result: Record<string, Encrypted> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (isEncryptedPayload(value)) {\n result[key] = value\n }\n }\n\n return result\n}\n\n/**\n * Helper function to extract non-encrypted fields from a model\n */\nexport function extractOtherFields<T extends Record<string, unknown>>(\n model: T,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (!isEncryptedPayload(value)) {\n result[key] = value\n }\n }\n\n return result\n}\n\n/**\n * Helper function to merge encrypted and non-encrypted fields into a model\n */\nexport function mergeFields<T>(\n otherFields: Record<string, unknown>,\n encryptedFields: Record<string, Encrypted>,\n): T {\n return { ...otherFields, ...encryptedFields } as T\n}\n\n/**\n * Base interface for bulk operation payloads\n */\ninterface BulkOperationPayload {\n id: string\n [key: string]: unknown\n}\n\n/**\n * Interface for bulk operation key mapping\n */\ninterface BulkOperationKeyMap {\n modelIndex: number\n fieldKey: string\n}\n\n/**\n * Helper function to handle single model bulk operations with mapping\n */\nasync function handleSingleModelBulkOperation<\n T extends BulkOperationPayload,\n R,\n>(\n items: T[],\n operation: (items: T[]) => Promise<R[]>,\n keyMap: Record<string, string>,\n): Promise<Record<string, R>> {\n if (items.length === 0) {\n return {}\n }\n\n const results = await operation(items)\n const mappedResults: Record<string, R> = {}\n\n results.forEach((result, index) => {\n const originalKey = keyMap[index.toString()]\n mappedResults[originalKey] = result\n })\n\n return mappedResults\n}\n\n/**\n * Helper function to handle multiple model bulk operations with mapping\n */\nasync function handleMultiModelBulkOperation<T extends BulkOperationPayload, R>(\n items: T[],\n operation: (items: T[]) => Promise<R[]>,\n keyMap: Record<string, BulkOperationKeyMap>,\n): Promise<Record<string, R>> {\n if (items.length === 0) {\n return {}\n }\n\n const results = await operation(items)\n const mappedResults: Record<string, R> = {}\n\n results.forEach((result, index) => {\n const key = index.toString()\n const { modelIndex, fieldKey } = keyMap[key]\n mappedResults[`${modelIndex}-${fieldKey}`] = result\n })\n\n return mappedResults\n}\n\n/**\n * Helper function to prepare fields for decryption\n */\nfunction prepareFieldsForDecryption<T extends Record<string, unknown>>(\n model: T,\n): {\n otherFields: Record<string, unknown>\n operationFields: Record<string, unknown>\n keyMap: Record<string, string>\n nullFields: Record<string, null | undefined>\n} {\n const otherFields = { ...model } as Record<string, unknown>\n const operationFields: Record<string, unknown> = {}\n const nullFields: Record<string, null | undefined> = {}\n const keyMap: Record<string, string> = {}\n let index = 0\n\n const processNestedFields = (obj: Record<string, unknown>, prefix = '') => {\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n\n if (value === null || value === undefined) {\n nullFields[fullKey] = value\n continue\n }\n\n if (typeof value === 'object' && !isEncryptedPayload(value)) {\n // Recursively process nested objects\n processNestedFields(value as Record<string, unknown>, fullKey)\n } else if (isEncryptedPayload(value)) {\n // This is an encrypted field\n const id = index.toString()\n keyMap[id] = fullKey\n operationFields[fullKey] = value\n index++\n\n // Remove from otherFields\n const parts = fullKey.split('.')\n let current = otherFields\n for (let i = 0; i < parts.length - 1; i++) {\n current = current[parts[i]] as Record<string, unknown>\n }\n delete current[parts[parts.length - 1]]\n }\n }\n }\n\n processNestedFields(model)\n return { otherFields, operationFields, keyMap, nullFields }\n}\n\n/**\n * Helper function to prepare fields for encryption\n */\nfunction prepareFieldsForEncryption<T extends Record<string, unknown>>(\n model: T,\n table: ProtectTable<ProtectTableColumn>,\n): {\n otherFields: Record<string, unknown>\n operationFields: Record<string, unknown>\n keyMap: Record<string, string>\n nullFields: Record<string, null | undefined>\n} {\n const otherFields = { ...model } as Record<string, unknown>\n const operationFields: Record<string, unknown> = {}\n const nullFields: Record<string, null | undefined> = {}\n const keyMap: Record<string, string> = {}\n let index = 0\n\n const processNestedFields = (\n obj: Record<string, unknown>,\n prefix = '',\n columnPaths: string[] = [],\n ) => {\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n\n if (value === null || value === undefined) {\n nullFields[fullKey] = value\n continue\n }\n\n if (\n typeof value === 'object' &&\n !isEncryptedPayload(value) &&\n !columnPaths.includes(fullKey)\n ) {\n // Only process nested objects if they're in the schema\n if (columnPaths.some((path) => path.startsWith(fullKey))) {\n processNestedFields(\n value as Record<string, unknown>,\n fullKey,\n columnPaths,\n )\n }\n } else if (columnPaths.includes(fullKey)) {\n // Only process fields that are explicitly defined in the schema\n const id = index.toString()\n keyMap[id] = fullKey\n operationFields[fullKey] = value\n index++\n\n // Remove from otherFields\n const parts = fullKey.split('.')\n let current = otherFields\n for (let i = 0; i < parts.length - 1; i++) {\n current = current[parts[i]] as Record<string, unknown>\n }\n delete current[parts[parts.length - 1]]\n }\n }\n }\n\n // Get all column paths from the table schema\n const columnPaths = Object.keys(table.build().columns)\n processNestedFields(model, '', columnPaths)\n\n return { otherFields, operationFields, keyMap, nullFields }\n}\n\n/**\n * Helper function to convert a model with encrypted fields to a decrypted model\n */\nexport async function decryptModelFields<T extends Record<string, unknown>>(\n model: T,\n client: Client,\n auditData?: AuditData,\n): Promise<Decrypted<T>> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareFieldsForDecryption(model)\n\n const bulkDecryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n ciphertext: value as CipherStashEncrypted,\n }),\n )\n\n const decryptedFields = await handleSingleModelBulkOperation(\n bulkDecryptPayload,\n (items) =>\n decryptBulk(client, {\n ciphertexts: items,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct the object with proper nesting\n const result: Record<string, unknown> = { ...otherFields }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the decrypted fields\n for (const [key, value] of Object.entries(decryptedFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as Decrypted<T>\n}\n\n/**\n * Helper function to convert a decrypted model to a model with encrypted fields\n */\nexport async function encryptModelFields<T extends Record<string, unknown>>(\n model: Decrypted<T>,\n table: ProtectTable<ProtectTableColumn>,\n client: Client,\n auditData?: AuditData,\n): Promise<T> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareFieldsForEncryption(model, table)\n\n const bulkEncryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n plaintext: value as string,\n table: table.tableName,\n column: key,\n }),\n )\n\n const encryptedData = await handleSingleModelBulkOperation(\n bulkEncryptPayload,\n (items) =>\n encryptBulk(client, {\n plaintexts: items,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct the object with proper nesting\n const result: Record<string, unknown> = { ...otherFields }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the encrypted fields\n for (const [key, value] of Object.entries(encryptedData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as T\n}\n\n/**\n * Helper function to convert a model with encrypted fields to a decrypted model with lock context\n */\nexport async function decryptModelFieldsWithLockContext<\n T extends Record<string, unknown>,\n>(\n model: T,\n client: Client,\n lockContext: GetLockContextResponse,\n auditData?: AuditData,\n): Promise<Decrypted<T>> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!lockContext) {\n throw new Error('Lock context is not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareFieldsForDecryption(model)\n\n const bulkDecryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n ciphertext: value as CipherStashEncrypted,\n lockContext: lockContext.context,\n }),\n )\n\n const decryptedFields = await handleSingleModelBulkOperation(\n bulkDecryptPayload,\n (items) =>\n decryptBulk(client, {\n ciphertexts: items,\n serviceToken: lockContext.ctsToken,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct the object with proper nesting\n const result: Record<string, unknown> = { ...otherFields }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the decrypted fields\n for (const [key, value] of Object.entries(decryptedFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as Decrypted<T>\n}\n\n/**\n * Helper function to convert a decrypted model to a model with encrypted fields with lock context\n */\nexport async function encryptModelFieldsWithLockContext<\n T extends Record<string, unknown>,\n>(\n model: Decrypted<T>,\n table: ProtectTable<ProtectTableColumn>,\n client: Client,\n lockContext: GetLockContextResponse,\n auditData?: AuditData,\n): Promise<T> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!lockContext) {\n throw new Error('Lock context is not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareFieldsForEncryption(model, table)\n\n const bulkEncryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n plaintext: value as string,\n table: table.tableName,\n column: key,\n lockContext: lockContext.context,\n }),\n )\n\n const encryptedData = await handleSingleModelBulkOperation(\n bulkEncryptPayload,\n (items) =>\n encryptBulk(client, {\n plaintexts: items,\n serviceToken: lockContext.ctsToken,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct the object with proper nesting\n const result: Record<string, unknown> = { ...otherFields }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the encrypted fields\n for (const [key, value] of Object.entries(encryptedData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as T\n}\n\n/**\n * Helper function to prepare multiple models for bulk operation\n */\nfunction prepareBulkModelsForOperation<T extends Record<string, unknown>>(\n models: T[],\n table?: ProtectTable<ProtectTableColumn>,\n): {\n otherFields: Record<string, unknown>[]\n operationFields: Record<string, unknown>[]\n keyMap: Record<string, { modelIndex: number; fieldKey: string }>\n nullFields: Record<string, null | undefined>[]\n} {\n const otherFields: Record<string, unknown>[] = []\n const operationFields: Record<string, unknown>[] = []\n const nullFields: Record<string, null | undefined>[] = []\n const keyMap: Record<string, { modelIndex: number; fieldKey: string }> = {}\n let index = 0\n\n for (let modelIndex = 0; modelIndex < models.length; modelIndex++) {\n const model = models[modelIndex]\n const modelOtherFields = { ...model } as Record<string, unknown>\n const modelOperationFields: Record<string, unknown> = {}\n const modelNullFields: Record<string, null | undefined> = {}\n\n const processNestedFields = (\n obj: Record<string, unknown>,\n prefix = '',\n columnPaths: string[] = [],\n ) => {\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n\n if (value === null || value === undefined) {\n modelNullFields[fullKey] = value\n continue\n }\n\n if (\n typeof value === 'object' &&\n !isEncryptedPayload(value) &&\n !columnPaths.includes(fullKey)\n ) {\n // Only process nested objects if they're in the schema\n if (columnPaths.some((path) => path.startsWith(fullKey))) {\n processNestedFields(\n value as Record<string, unknown>,\n fullKey,\n columnPaths,\n )\n }\n } else if (columnPaths.includes(fullKey)) {\n // Only process fields that are explicitly defined in the schema\n const id = index.toString()\n keyMap[id] = { modelIndex, fieldKey: fullKey }\n modelOperationFields[fullKey] = value\n index++\n\n // Remove from otherFields\n const parts = fullKey.split('.')\n let current = modelOtherFields\n for (let i = 0; i < parts.length - 1; i++) {\n current = current[parts[i]] as Record<string, unknown>\n }\n delete current[parts[parts.length - 1]]\n }\n }\n }\n\n if (table) {\n // Get all column paths from the table schema\n const columnPaths = Object.keys(table.build().columns)\n processNestedFields(model, '', columnPaths)\n } else {\n // For decryption, process all encrypted fields\n const processEncryptedFields = (\n obj: Record<string, unknown>,\n prefix = '',\n columnPaths: string[] = [],\n ) => {\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n\n if (value === null || value === undefined) {\n modelNullFields[fullKey] = value\n continue\n }\n\n if (\n typeof value === 'object' &&\n !isEncryptedPayload(value) &&\n !columnPaths.includes(fullKey)\n ) {\n // Recursively process nested objects\n processEncryptedFields(\n value as Record<string, unknown>,\n fullKey,\n columnPaths,\n )\n } else if (isEncryptedPayload(value)) {\n // This is an encrypted field\n const id = index.toString()\n keyMap[id] = { modelIndex, fieldKey: fullKey }\n modelOperationFields[fullKey] = value\n index++\n\n // Remove from otherFields\n const parts = fullKey.split('.')\n let current = modelOtherFields\n for (let i = 0; i < parts.length - 1; i++) {\n current = current[parts[i]] as Record<string, unknown>\n }\n delete current[parts[parts.length - 1]]\n }\n }\n }\n processEncryptedFields(model)\n }\n\n otherFields.push(modelOtherFields)\n operationFields.push(modelOperationFields)\n nullFields.push(modelNullFields)\n }\n\n return { otherFields, operationFields, keyMap, nullFields }\n}\n\n/**\n * Helper function to convert multiple decrypted models to models with encrypted fields\n */\nexport async function bulkEncryptModels<T extends Record<string, unknown>>(\n models: Decrypted<T>[],\n table: ProtectTable<ProtectTableColumn>,\n client: Client,\n auditData?: AuditData,\n): Promise<T[]> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!models || models.length === 0) {\n return []\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareBulkModelsForOperation(models, table)\n\n const bulkEncryptPayload = operationFields.flatMap((fields, modelIndex) =>\n Object.entries(fields).map(([key, value]) => ({\n id: `${modelIndex}-${key}`,\n plaintext: value as string,\n table: table.tableName,\n column: key,\n })),\n )\n\n const encryptedData = await handleMultiModelBulkOperation(\n bulkEncryptPayload,\n (items) =>\n encryptBulk(client, {\n plaintexts: items,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n return models.map((_, modelIndex) => {\n const result: Record<string, unknown> = { ...otherFields[modelIndex] }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields[modelIndex])) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the encrypted fields\n const modelData = Object.fromEntries(\n Object.entries(encryptedData)\n .filter(([key]) => {\n const [idx] = key.split('-')\n return Number.parseInt(idx) === modelIndex\n })\n .map(([key, value]) => {\n const [_, fieldKey] = key.split('-')\n return [fieldKey, value]\n }),\n )\n\n for (const [key, value] of Object.entries(modelData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as T\n })\n}\n\n/**\n * Helper function to convert multiple models with encrypted fields to decrypted models\n */\nexport async function bulkDecryptModels<T extends Record<string, unknown>>(\n models: T[],\n client: Client,\n auditData?: AuditData,\n): Promise<Decrypted<T>[]> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!models || models.length === 0) {\n return []\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareBulkModelsForOperation(models)\n\n const bulkDecryptPayload = operationFields.flatMap((fields, modelIndex) =>\n Object.entries(fields).map(([key, value]) => ({\n id: `${modelIndex}-${key}`,\n ciphertext: value as CipherStashEncrypted,\n })),\n )\n\n const decryptedFields = await handleMultiModelBulkOperation(\n bulkDecryptPayload,\n (items) =>\n decryptBulk(client, {\n ciphertexts: items,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n return models.map((_, modelIndex) => {\n const result: Record<string, unknown> = { ...otherFields[modelIndex] }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields[modelIndex])) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the decrypted fields\n const modelData = Object.fromEntries(\n Object.entries(decryptedFields)\n .filter(([key]) => {\n const [idx] = key.split('-')\n return Number.parseInt(idx) === modelIndex\n })\n .map(([key, value]) => {\n const [_, fieldKey] = key.split('-')\n return [fieldKey, value]\n }),\n )\n\n for (const [key, value] of Object.entries(modelData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as Decrypted<T>\n })\n}\n\n/**\n * Helper function to convert multiple models with encrypted fields to decrypted models with lock context\n */\nexport async function bulkDecryptModelsWithLockContext<\n T extends Record<string, unknown>,\n>(\n models: T[],\n client: Client,\n lockContext: GetLockContextResponse,\n auditData?: AuditData,\n): Promise<Decrypted<T>[]> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!lockContext) {\n throw new Error('Lock context is not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareBulkModelsForOperation(models)\n\n const bulkDecryptPayload = operationFields.flatMap((fields, modelIndex) =>\n Object.entries(fields).map(([key, value]) => ({\n id: `${modelIndex}-${key}`,\n ciphertext: value as CipherStashEncrypted,\n lockContext: lockContext.context,\n })),\n )\n\n const decryptedFields = await handleMultiModelBulkOperation(\n bulkDecryptPayload,\n (items) =>\n decryptBulk(client, {\n ciphertexts: items,\n serviceToken: lockContext.ctsToken,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct models\n return models.map((_, modelIndex) => {\n const result: Record<string, unknown> = { ...otherFields[modelIndex] }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields[modelIndex])) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the decrypted fields\n const modelData = Object.fromEntries(\n Object.entries(decryptedFields)\n .filter(([key]) => {\n const [idx] = key.split('-')\n return Number.parseInt(idx) === modelIndex\n })\n .map(([key, value]) => {\n const [_, fieldKey] = key.split('-')\n return [fieldKey, value]\n }),\n )\n\n for (const [key, value] of Object.entries(modelData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as Decrypted<T>\n })\n}\n\n/**\n * Helper function to convert multiple decrypted models to models with encrypted fields with lock context\n */\nexport async function bulkEncryptModelsWithLockContext<\n T extends Record<string, unknown>,\n>(\n models: Decrypted<T>[],\n table: ProtectTable<ProtectTableColumn>,\n client: Client,\n lockContext: GetLockContextResponse,\n auditData?: AuditData,\n): Promise<T[]> {\n if (!client) {\n throw new Error('Client not initialized')\n }\n\n if (!lockContext) {\n throw new Error('Lock context is not initialized')\n }\n\n const { otherFields, operationFields, keyMap, nullFields } =\n prepareBulkModelsForOperation(models, table)\n\n const bulkEncryptPayload = operationFields.flatMap((fields, modelIndex) =>\n Object.entries(fields).map(([key, value]) => ({\n id: `${modelIndex}-${key}`,\n plaintext: value as string,\n table: table.tableName,\n column: key,\n lockContext: lockContext.context,\n })),\n )\n\n const encryptedData = await handleMultiModelBulkOperation(\n bulkEncryptPayload,\n (items) =>\n encryptBulk(client, {\n plaintexts: items,\n serviceToken: lockContext.ctsToken,\n unverifiedContext: auditData?.metadata,\n }),\n keyMap,\n )\n\n // Reconstruct models\n return models.map((_, modelIndex) => {\n const result: Record<string, unknown> = { ...otherFields[modelIndex] }\n\n // First, reconstruct the null/undefined fields\n for (const [key, value] of Object.entries(nullFields[modelIndex])) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n // Then, reconstruct the encrypted fields\n const modelData = Object.fromEntries(\n Object.entries(encryptedData)\n .filter(([key]) => {\n const [idx] = key.split('-')\n return Number.parseInt(idx) === modelIndex\n })\n .map(([key, value]) => {\n const [_, fieldKey] = key.split('-')\n return [fieldKey, value]\n }),\n )\n\n for (const [key, value] of Object.entries(modelData)) {\n const parts = key.split('.')\n setNestedValue(result, parts, value)\n }\n\n return result as T\n })\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { Context, LockContext } from '@/identity'\nimport type {\n ProtectColumn,\n ProtectTable,\n ProtectTableColumn,\n ProtectValue,\n} from '@/schema'\nimport type {\n BulkEncryptPayload,\n BulkEncryptedData,\n Client,\n EncryptOptions,\n Encrypted,\n} from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { type JsPlaintext, encryptBulk } from '@cipherstash/protect-ffi'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n// Helper functions for better composability\nconst createEncryptPayloads = (\n plaintexts: BulkEncryptPayload,\n column: ProtectColumn | ProtectValue,\n table: ProtectTable<ProtectTableColumn>,\n lockContext?: Context,\n) => {\n return plaintexts\n .map((item, index) => ({ ...item, originalIndex: index }))\n .filter(({ plaintext }) => plaintext !== null)\n .map(({ id, plaintext, originalIndex }) => ({\n id,\n plaintext: plaintext as JsPlaintext,\n column: column.getName(),\n table: table.tableName,\n originalIndex,\n ...(lockContext && { lockContext }),\n }))\n}\n\nconst createNullResult = (\n plaintexts: BulkEncryptPayload,\n): BulkEncryptedData => {\n return plaintexts.map(({ id }) => ({ id, data: null }))\n}\n\nconst mapEncryptedDataToResult = (\n plaintexts: BulkEncryptPayload,\n encryptedData: Encrypted[],\n): BulkEncryptedData => {\n const result: BulkEncryptedData = new Array(plaintexts.length)\n let encryptedIndex = 0\n\n for (let i = 0; i < plaintexts.length; i++) {\n if (plaintexts[i].plaintext === null) {\n result[i] = { id: plaintexts[i].id, data: null }\n } else {\n result[i] = {\n id: plaintexts[i].id,\n data: encryptedData[encryptedIndex],\n }\n encryptedIndex++\n }\n }\n\n return result\n}\n\nexport class BulkEncryptOperation extends EncryptionOperation<BulkEncryptedData> {\n private client: Client\n private plaintexts: BulkEncryptPayload\n private column: ProtectColumn | ProtectValue\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n client: Client,\n plaintexts: BulkEncryptPayload,\n opts: EncryptOptions,\n ) {\n super()\n this.client = client\n this.plaintexts = plaintexts\n this.column = opts.column\n this.table = opts.table\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): BulkEncryptOperationWithLockContext {\n return new BulkEncryptOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<BulkEncryptedData, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'bulkEncrypt',\n table: this.table.tableName,\n column: this.column.getName(),\n count: this.plaintexts?.length ?? 0,\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n if (!this.plaintexts || this.plaintexts.length === 0) {\n return []\n }\n\n const nonNullPayloads = createEncryptPayloads(\n this.plaintexts,\n this.column,\n this.table,\n )\n\n if (nonNullPayloads.length === 0) {\n return createNullResult(this.plaintexts)\n }\n\n const { metadata } = this.getAuditData()\n\n const encryptedData = await encryptBulk(this.client, {\n plaintexts: nonNullPayloads,\n unverifiedContext: metadata,\n })\n\n return mapEncryptedDataToResult(this.plaintexts, encryptedData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n plaintexts: BulkEncryptPayload\n column: ProtectColumn | ProtectValue\n table: ProtectTable<ProtectTableColumn>\n } {\n return {\n client: this.client,\n plaintexts: this.plaintexts,\n column: this.column,\n table: this.table,\n }\n }\n}\n\nexport class BulkEncryptOperationWithLockContext extends EncryptionOperation<BulkEncryptedData> {\n private operation: BulkEncryptOperation\n private lockContext: LockContext\n\n constructor(operation: BulkEncryptOperation, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<BulkEncryptedData, EncryptionError>> {\n const { client, plaintexts, column, table } =\n this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'bulkEncrypt',\n table: table.tableName,\n column: column.getName(),\n count: plaintexts?.length ?? 0,\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) {\n throw noClientError()\n }\n if (!plaintexts || plaintexts.length === 0) {\n return []\n }\n\n const context = await this.lockContext.getLockContext()\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const nonNullPayloads = createEncryptPayloads(\n plaintexts,\n column,\n table,\n context.data.context,\n )\n\n if (nonNullPayloads.length === 0) {\n return createNullResult(plaintexts)\n }\n\n const { metadata } = this.getAuditData()\n\n const encryptedData = await encryptBulk(client, {\n plaintexts: nonNullPayloads,\n serviceToken: context.data.ctsToken,\n unverifiedContext: metadata,\n })\n\n return mapEncryptedDataToResult(plaintexts, encryptedData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { noClientError } from '../index'\nimport {\n bulkEncryptModels,\n bulkEncryptModelsWithLockContext,\n} from '../model-helpers'\nimport { EncryptionOperation } from './base-operation'\n\nexport class BulkEncryptModelsOperation<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<T[]> {\n private client: Client\n private models: Decrypted<T>[]\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n client: Client,\n models: Decrypted<T>[],\n table: ProtectTable<ProtectTableColumn>,\n ) {\n super()\n this.client = client\n this.models = models\n this.table = table\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): BulkEncryptModelsOperationWithLockContext<T> {\n return new BulkEncryptModelsOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<T[], EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'bulkEncryptModels',\n table: this.table.tableName,\n count: this.models.length,\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n const auditData = this.getAuditData()\n\n return await bulkEncryptModels<T>(\n this.models,\n this.table,\n this.client,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n models: Decrypted<T>[]\n table: ProtectTable<ProtectTableColumn>\n } {\n return {\n client: this.client,\n models: this.models,\n table: this.table,\n }\n }\n}\n\nexport class BulkEncryptModelsOperationWithLockContext<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<T[]> {\n private operation: BulkEncryptModelsOperation<T>\n private lockContext: LockContext\n\n constructor(\n operation: BulkEncryptModelsOperation<T>,\n lockContext: LockContext,\n ) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<T[], EncryptionError>> {\n const { client, models, table } = this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'bulkEncryptModels',\n table: table.tableName,\n count: models.length,\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) {\n throw noClientError()\n }\n\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const auditData = this.getAuditData()\n\n return await bulkEncryptModelsWithLockContext<T>(\n models,\n table,\n client,\n context.data,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { Client, Encrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport {\n type JsPlaintext,\n decrypt as ffiDecrypt,\n} from '@cipherstash/protect-ffi'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n/**\n * Decrypts an encrypted payload using the provided client.\n * This is the type returned by the {@link EncryptionClient.decrypt | decrypt} method of the {@link EncryptionClient}.\n */\nexport class DecryptOperation extends EncryptionOperation<JsPlaintext | null> {\n private client: Client\n private encryptedData: Encrypted\n\n constructor(client: Client, encryptedData: Encrypted) {\n super()\n this.client = client\n this.encryptedData = encryptedData\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): DecryptOperationWithLockContext {\n return new DecryptOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<JsPlaintext | null, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'decrypt',\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n if (this.encryptedData === null) {\n return null\n }\n\n const { metadata } = this.getAuditData()\n\n return await ffiDecrypt(this.client, {\n ciphertext: this.encryptedData,\n unverifiedContext: metadata,\n })\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n encryptedData: Encrypted\n auditData?: Record<string, unknown>\n } {\n return {\n client: this.client,\n encryptedData: this.encryptedData,\n auditData: this.getAuditData(),\n }\n }\n}\n\nexport class DecryptOperationWithLockContext extends EncryptionOperation<JsPlaintext | null> {\n private operation: DecryptOperation\n private lockContext: LockContext\n\n constructor(operation: DecryptOperation, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<JsPlaintext | null, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'decrypt',\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n const { client, encryptedData } = this.operation.getOperation()\n\n if (!client) {\n throw noClientError()\n }\n\n if (encryptedData === null) {\n return null\n }\n\n const { metadata } = this.getAuditData()\n\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n return await ffiDecrypt(client, {\n ciphertext: encryptedData,\n unverifiedContext: metadata,\n lockContext: context.data.context,\n serviceToken: context.data.ctsToken,\n })\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { noClientError } from '../index'\nimport {\n decryptModelFields,\n decryptModelFieldsWithLockContext,\n} from '../model-helpers'\nimport { EncryptionOperation } from './base-operation'\n\nexport class DecryptModelOperation<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<Decrypted<T>> {\n private client: Client\n private model: T\n\n constructor(client: Client, model: T) {\n super()\n this.client = client\n this.model = model\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): DecryptModelOperationWithLockContext<T> {\n return new DecryptModelOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<Decrypted<T>, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'decryptModel',\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n const auditData = this.getAuditData()\n\n return await decryptModelFields<T>(this.model, this.client, auditData)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n model: T\n } {\n return {\n client: this.client,\n model: this.model,\n }\n }\n}\n\nexport class DecryptModelOperationWithLockContext<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<Decrypted<T>> {\n private operation: DecryptModelOperation<T>\n private lockContext: LockContext\n\n constructor(operation: DecryptModelOperation<T>, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<Decrypted<T>, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'decryptModel',\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n const { client, model } = this.operation.getOperation()\n\n if (!client) {\n throw noClientError()\n }\n\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const auditData = this.getAuditData()\n\n return await decryptModelFieldsWithLockContext<T>(\n model,\n client,\n context.data,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.DecryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type {\n ProtectColumn,\n ProtectTable,\n ProtectTableColumn,\n ProtectValue,\n} from '@/schema'\nimport type { Client, EncryptOptions, Encrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport {\n type JsPlaintext,\n encrypt as ffiEncrypt,\n} from '@cipherstash/protect-ffi'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\nexport class EncryptOperation extends EncryptionOperation<Encrypted> {\n private client: Client\n private plaintext: JsPlaintext | null\n private column: ProtectColumn | ProtectValue\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n client: Client,\n plaintext: JsPlaintext | null,\n opts: EncryptOptions,\n ) {\n super()\n this.client = client\n this.plaintext = plaintext\n this.column = opts.column\n this.table = opts.table\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): EncryptOperationWithLockContext {\n return new EncryptOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<Encrypted, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'encrypt',\n table: this.table.tableName,\n column: this.column.getName(),\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n if (this.plaintext === null) {\n return null\n }\n\n if (\n typeof this.plaintext === 'number' &&\n Number.isNaN(this.plaintext)\n ) {\n throw new Error('[encryption]: Cannot encrypt NaN value')\n }\n\n if (\n typeof this.plaintext === 'number' &&\n !Number.isFinite(this.plaintext)\n ) {\n throw new Error('[encryption]: Cannot encrypt Infinity value')\n }\n\n const { metadata } = this.getAuditData()\n\n return await ffiEncrypt(this.client, {\n plaintext: this.plaintext,\n column: this.column.getName(),\n table: this.table.tableName,\n unverifiedContext: metadata,\n })\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n plaintext: JsPlaintext | null\n column: ProtectColumn | ProtectValue\n table: ProtectTable<ProtectTableColumn>\n } {\n return {\n client: this.client,\n plaintext: this.plaintext,\n column: this.column,\n table: this.table,\n }\n }\n}\n\nexport class EncryptOperationWithLockContext extends EncryptionOperation<Encrypted> {\n private operation: EncryptOperation\n private lockContext: LockContext\n\n constructor(operation: EncryptOperation, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<Encrypted, EncryptionError>> {\n const { client, plaintext, column, table } =\n this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'encrypt',\n table: table.tableName,\n column: column.getName(),\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) {\n throw noClientError()\n }\n\n if (plaintext === null) {\n return null\n }\n\n const { metadata } = this.getAuditData()\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n return await ffiEncrypt(client, {\n plaintext,\n column: column.getName(),\n table: table.tableName,\n lockContext: context.data.context,\n serviceToken: context.data.ctsToken,\n unverifiedContext: metadata,\n })\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport { noClientError } from '../index'\nimport {\n encryptModelFields,\n encryptModelFieldsWithLockContext,\n} from '../model-helpers'\nimport { EncryptionOperation } from './base-operation'\n\nexport class EncryptModelOperation<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<T> {\n private client: Client\n private model: Decrypted<T>\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n client: Client,\n model: Decrypted<T>,\n table: ProtectTable<ProtectTableColumn>,\n ) {\n super()\n this.client = client\n this.model = model\n this.table = table\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): EncryptModelOperationWithLockContext<T> {\n return new EncryptModelOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<T, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'encryptModel',\n table: this.table.tableName,\n lockContext: false,\n })\n\n const result = await withResult(\n async () => {\n if (!this.client) {\n throw noClientError()\n }\n\n const auditData = this.getAuditData()\n\n return await encryptModelFields<T>(\n this.model,\n this.table,\n this.client,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation(): {\n client: Client\n model: Decrypted<T>\n table: ProtectTable<ProtectTableColumn>\n } {\n return {\n client: this.client,\n model: this.model,\n table: this.table,\n }\n }\n}\n\nexport class EncryptModelOperationWithLockContext<\n T extends Record<string, unknown>,\n> extends EncryptionOperation<T> {\n private operation: EncryptModelOperation<T>\n private lockContext: LockContext\n\n constructor(operation: EncryptModelOperation<T>, lockContext: LockContext) {\n super()\n this.operation = operation\n this.lockContext = lockContext\n const auditData = operation.getAuditData()\n if (auditData) {\n this.audit(auditData)\n }\n }\n\n public async execute(): Promise<Result<T, EncryptionError>> {\n const { client, model, table } = this.operation.getOperation()\n\n const log = createRequestLogger()\n log.set({\n op: 'encryptModel',\n table: table.tableName,\n lockContext: true,\n })\n\n const result = await withResult(\n async () => {\n if (!client) {\n throw noClientError()\n }\n\n const context = await this.lockContext.getLockContext()\n\n if (context.failure) {\n throw new Error(`[encryption]: ${context.failure.message}`)\n }\n\n const auditData = this.getAuditData()\n\n return await encryptModelFieldsWithLockContext<T>(\n model,\n table,\n client,\n context.data,\n auditData,\n )\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { getErrorCode } from '@/encryption/ffi/helpers/error-code'\nimport { formatEncryptedResult } from '@/encryption/helpers'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContext } from '@/identity'\nimport type { Client, EncryptQueryOptions, EncryptedQueryResult } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { type Result, withResult } from '@byteslice/result'\nimport {\n type JsPlaintext,\n encryptQuery as ffiEncryptQuery,\n} from '@cipherstash/protect-ffi'\nimport { resolveIndexType } from '../helpers/infer-index-type'\nimport {\n assertValueIndexCompatibility,\n validateNumericValue,\n} from '../helpers/validation'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n/**\n * @internal Use {@link EncryptionClient.encryptQuery} instead.\n */\nexport class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryResult> {\n constructor(\n private client: Client,\n private plaintext: JsPlaintext | null,\n private opts: EncryptQueryOptions,\n ) {\n super()\n }\n\n public withLockContext(\n lockContext: LockContext,\n ): EncryptQueryOperationWithLockContext {\n return new EncryptQueryOperationWithLockContext(\n this.client,\n this.plaintext,\n this.opts,\n lockContext,\n this.auditMetadata,\n )\n }\n\n public async execute(): Promise<Result<EncryptedQueryResult, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'encryptQuery',\n table: this.opts.table.tableName,\n column: this.opts.column.getName(),\n queryType: this.opts.queryType,\n lockContext: false,\n })\n\n if (this.plaintext === null || this.plaintext === undefined) {\n log.emit()\n return { data: null }\n }\n\n const validationError = validateNumericValue(this.plaintext)\n if (validationError?.failure) {\n log.emit()\n return { failure: validationError.failure }\n }\n\n const result = await withResult(\n async () => {\n if (!this.client) throw noClientError()\n\n const { metadata } = this.getAuditData()\n\n const { indexType, queryOp } = resolveIndexType(\n this.opts.column,\n this.opts.queryType,\n this.plaintext,\n )\n\n // Validate value/index compatibility\n assertValueIndexCompatibility(\n this.plaintext,\n indexType,\n this.opts.column.getName(),\n )\n\n const encrypted = await ffiEncryptQuery(this.client, {\n plaintext: this.plaintext as JsPlaintext,\n column: this.opts.column.getName(),\n table: this.opts.table.tableName,\n indexType,\n queryOp,\n unverifiedContext: metadata,\n })\n\n return formatEncryptedResult(encrypted, this.opts.returnType)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n\n public getOperation() {\n return { client: this.client, plaintext: this.plaintext, ...this.opts }\n }\n}\n\n/**\n * @internal Use {@link EncryptionClient.encryptQuery} with `.withLockContext()` instead.\n */\nexport class EncryptQueryOperationWithLockContext extends EncryptionOperation<EncryptedQueryResult> {\n constructor(\n private client: Client,\n private plaintext: JsPlaintext | null,\n private opts: EncryptQueryOptions,\n private lockContext: LockContext,\n auditMetadata?: Record<string, unknown>,\n ) {\n super()\n this.auditMetadata = auditMetadata\n }\n\n public async execute(): Promise<Result<EncryptedQueryResult, EncryptionError>> {\n const log = createRequestLogger()\n log.set({\n op: 'encryptQuery',\n table: this.opts.table.tableName,\n column: this.opts.column.getName(),\n queryType: this.opts.queryType,\n lockContext: true,\n })\n\n if (this.plaintext === null || this.plaintext === undefined) {\n log.emit()\n return { data: null }\n }\n\n const validationError = validateNumericValue(this.plaintext)\n if (validationError?.failure) {\n log.emit()\n return { failure: validationError.failure }\n }\n\n const lockContextResult = await this.lockContext.getLockContext()\n if (lockContextResult.failure) {\n log.emit()\n return { failure: lockContextResult.failure }\n }\n\n const { ctsToken, context } = lockContextResult.data\n\n const result = await withResult(\n async () => {\n if (!this.client) throw noClientError()\n\n const { metadata } = this.getAuditData()\n\n const { indexType, queryOp } = resolveIndexType(\n this.opts.column,\n this.opts.queryType,\n this.plaintext,\n )\n\n // Validate value/index compatibility\n assertValueIndexCompatibility(\n this.plaintext,\n indexType,\n this.opts.column.getName(),\n )\n\n const encrypted = await ffiEncryptQuery(this.client, {\n plaintext: this.plaintext as JsPlaintext,\n column: this.opts.column.getName(),\n table: this.opts.table.tableName,\n indexType,\n queryOp,\n lockContext: context,\n serviceToken: ctsToken,\n unverifiedContext: metadata,\n })\n\n return formatEncryptedResult(encrypted, this.opts.returnType)\n },\n (error: unknown) => {\n log.set({ errorCode: getErrorCode(error) ?? 'unknown' })\n return {\n type: EncryptionErrorTypes.EncryptionError,\n message: (error as Error).message,\n code: getErrorCode(error),\n }\n },\n )\n log.emit()\n return result\n }\n}\n","import { EncryptionClient } from '@/encryption/ffi'\nimport { buildEncryptConfig } from '@/schema'\nimport type { EncryptionClientConfig } from '@/types'\nimport { initStackLogger } from '@/utils/logger'\n\n// Re-export schema builders for convenience\nexport { encryptedTable, encryptedColumn, encryptedValue } from '@/schema'\nexport type {\n InferPlaintext,\n InferEncrypted,\n ProtectColumn,\n ProtectTable,\n ProtectTableColumn,\n ProtectValue,\n} from '@/schema'\n\n// Re-export error types\nexport { EncryptionErrorTypes, getErrorMessage } from '@/errors'\nexport type {\n EncryptionError,\n StackError,\n ClientInitError,\n EncryptionOperationError,\n DecryptionOperationError,\n LockContextError,\n CtsTokenError,\n} from '@/errors'\n\nfunction isValidUuid(uuid: string): boolean {\n const uuidRegex =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n return uuidRegex.test(uuid)\n}\n\n/** Initialize an Encryption client with the provided configuration.\n\n @param config - The configuration object for initializing the Encryption client.\n\n @see {@link EncryptionClientConfig} for details on the configuration options.\n\n @returns A Promise that resolves to an instance of EncryptionClient.\n\n @throws Will throw an error if no schemas are provided or if the keyset ID is not a valid UUID.\n*/\nexport const Encryption = async (\n config: EncryptionClientConfig,\n): Promise<EncryptionClient> => {\n if (config.logging) {\n initStackLogger(config.logging)\n }\n\n const { schemas, config: clientConfig } = config\n\n if (!schemas.length) {\n throw new Error(\n '[encryption]: At least one encryptedTable must be provided to initialize the encryption client',\n )\n }\n\n if (\n clientConfig?.keyset &&\n 'id' in clientConfig.keyset &&\n !isValidUuid(clientConfig.keyset.id)\n ) {\n throw new Error(\n '[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID.',\n )\n }\n\n const client = new EncryptionClient(clientConfig?.workspaceCrn)\n const encryptConfig = buildEncryptConfig(...schemas)\n\n const result = await client.init({\n encryptConfig,\n ...clientConfig,\n })\n\n if (result.failure) {\n throw new Error(`[encryption]: ${result.failure.message}`)\n }\n\n return result.data\n}\n"],"mappings":"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","names":["path","fs","import_result","import_protect_ffi","FfiProtectError","import_protect_ffi","ffiEncryptQueryBulk","import_result","import_protect_ffi","import_result","import_protect_ffi","path","columnPaths","path","_","import_result","import_protect_ffi","createNullResult","import_result","import_result","import_protect_ffi","ffiDecrypt","import_result","import_result","import_protect_ffi","ffiEncrypt","import_result","import_result","import_protect_ffi","ffiEncryptQuery","path"]}