@cipherstash/stack 0.16.0 → 0.19.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 (102) hide show
  1. package/CHANGELOG.md +225 -0
  2. package/README.md +2 -2
  3. package/dist/{chunk-CY5B4LIF.js → chunk-36AA7IBJ.js} +303 -204
  4. package/dist/chunk-36AA7IBJ.js.map +1 -0
  5. package/dist/{chunk-MD6742R6.js → chunk-4AVL4VZD.js} +1 -1
  6. package/dist/chunk-4AVL4VZD.js.map +1 -0
  7. package/dist/{chunk-4RNBI3UH.js → chunk-BNO32ZMV.js} +1 -1
  8. package/dist/chunk-BNO32ZMV.js.map +1 -0
  9. package/dist/{chunk-6FD7OBGM.js → chunk-HQANMV7R.js} +3 -3
  10. package/dist/chunk-HQANMV7R.js.map +1 -0
  11. package/dist/chunk-IADZCZEA.js +23 -0
  12. package/dist/chunk-IADZCZEA.js.map +1 -0
  13. package/dist/chunk-IBSK6P33.js +209 -0
  14. package/dist/chunk-IBSK6P33.js.map +1 -0
  15. package/dist/chunk-JSG2AMDI.js +17 -0
  16. package/dist/chunk-JSG2AMDI.js.map +1 -0
  17. package/dist/chunk-MP3SSDNN.js +4439 -0
  18. package/dist/chunk-MP3SSDNN.js.map +1 -0
  19. package/dist/chunk-OFQ555AX.js +191 -0
  20. package/dist/chunk-OFQ555AX.js.map +1 -0
  21. package/dist/chunk-PZ5AY32C.js +10 -0
  22. package/dist/chunk-PZ5AY32C.js.map +1 -0
  23. package/dist/chunk-U66S7VIF.js +435 -0
  24. package/dist/chunk-U66S7VIF.js.map +1 -0
  25. package/dist/{client-C_7TF8EL.d.cts → client-DSGHBN-g.d.cts} +209 -72
  26. package/dist/{client-BLbA6aFD.d.ts → client-DfCrlHXh.d.ts} +209 -72
  27. package/dist/client.cjs +4103 -43
  28. package/dist/client.cjs.map +1 -1
  29. package/dist/client.d.cts +5 -5
  30. package/dist/client.d.ts +5 -5
  31. package/dist/client.js +3 -1
  32. package/dist/drizzle/index.cjs +4139 -77
  33. package/dist/drizzle/index.cjs.map +1 -1
  34. package/dist/drizzle/index.d.cts +33 -33
  35. package/dist/drizzle/index.d.ts +33 -33
  36. package/dist/drizzle/index.js +39 -33
  37. package/dist/drizzle/index.js.map +1 -1
  38. package/dist/dynamodb/index.cjs +31 -14
  39. package/dist/dynamodb/index.cjs.map +1 -1
  40. package/dist/dynamodb/index.d.cts +12 -12
  41. package/dist/dynamodb/index.d.ts +12 -12
  42. package/dist/dynamodb/index.js +16 -12
  43. package/dist/dynamodb/index.js.map +1 -1
  44. package/dist/encryption/index.cjs +4611 -257
  45. package/dist/encryption/index.cjs.map +1 -1
  46. package/dist/encryption/index.d.cts +3 -3
  47. package/dist/encryption/index.d.ts +3 -3
  48. package/dist/encryption/index.js +35 -7
  49. package/dist/encryption/v3.cjs +7791 -0
  50. package/dist/encryption/v3.cjs.map +1 -0
  51. package/dist/encryption/v3.d.cts +100 -0
  52. package/dist/encryption/v3.d.ts +100 -0
  53. package/dist/encryption/v3.js +161 -0
  54. package/dist/encryption/v3.js.map +1 -0
  55. package/dist/eql/v3/index.cjs +612 -0
  56. package/dist/eql/v3/index.cjs.map +1 -0
  57. package/dist/eql/v3/index.d.cts +71 -0
  58. package/dist/eql/v3/index.d.ts +71 -0
  59. package/dist/eql/v3/index.js +89 -0
  60. package/dist/eql/v3/index.js.map +1 -0
  61. package/dist/errors/index.js +1 -0
  62. package/dist/identity/index.cjs +55 -35
  63. package/dist/identity/index.cjs.map +1 -1
  64. package/dist/identity/index.d.cts +54 -30
  65. package/dist/identity/index.d.ts +54 -30
  66. package/dist/identity/index.js +9 -177
  67. package/dist/identity/index.js.map +1 -1
  68. package/dist/index.cjs +4625 -273
  69. package/dist/index.cjs.map +1 -1
  70. package/dist/index.d.cts +18 -7
  71. package/dist/index.d.ts +18 -7
  72. package/dist/index.js +20 -5
  73. package/dist/index.js.map +1 -1
  74. package/dist/schema/index.cjs +4108 -44
  75. package/dist/schema/index.cjs.map +1 -1
  76. package/dist/schema/index.d.cts +1 -1
  77. package/dist/schema/index.d.ts +1 -1
  78. package/dist/schema/index.js +3 -1
  79. package/dist/supabase/index.cjs +4500 -75
  80. package/dist/supabase/index.cjs.map +1 -1
  81. package/dist/supabase/index.d.cts +113 -34
  82. package/dist/supabase/index.d.ts +113 -34
  83. package/dist/supabase/index.js +350 -32
  84. package/dist/supabase/index.js.map +1 -1
  85. package/dist/table-CIH7jZ2h.d.ts +603 -0
  86. package/dist/table-DihEAlxG.d.cts +603 -0
  87. package/dist/{types-public-Dv-r6Ik0.d.ts → types-public-CpS5KjwX.d.cts} +209 -36
  88. package/dist/{types-public-Dv-r6Ik0.d.cts → types-public-CpS5KjwX.d.ts} +209 -36
  89. package/dist/types-public.cjs.map +1 -1
  90. package/dist/types-public.d.cts +2 -2
  91. package/dist/types-public.d.ts +2 -2
  92. package/dist/types-public.js +2 -1
  93. package/dist/wasm-inline.d.ts +1269 -0
  94. package/dist/wasm-inline.js +4594 -0
  95. package/dist/wasm-inline.js.map +1 -0
  96. package/package.json +63 -13
  97. package/dist/chunk-4RNBI3UH.js.map +0 -1
  98. package/dist/chunk-6FD7OBGM.js.map +0 -1
  99. package/dist/chunk-CY5B4LIF.js.map +0 -1
  100. package/dist/chunk-JDZ2QUUF.js +0 -381
  101. package/dist/chunk-JDZ2QUUF.js.map +0 -1
  102. package/dist/chunk-MD6742R6.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/encryption/index.ts","../../../node_modules/.pnpm/uuid@14.0.0/node_modules/uuid/dist-node/regex.js","../../../node_modules/.pnpm/uuid@14.0.0/node_modules/uuid/dist-node/validate.js","../src/encryption/helpers/type-guards.ts","../src/encryption/operations/batch-encrypt-query.ts","../src/encryption/helpers/error-code.ts","../src/encryption/helpers/infer-index-type.ts","../src/encryption/helpers/validation.ts","../src/encryption/operations/base-operation.ts","../src/encryption/operations/bulk-decrypt.ts","../src/encryption/helpers/model-helpers.ts","../src/encryption/operations/bulk-decrypt-models.ts","../src/encryption/operations/bulk-encrypt.ts","../src/encryption/operations/bulk-encrypt-models.ts","../src/encryption/operations/decrypt.ts","../src/encryption/operations/decrypt-model.ts","../src/encryption/operations/encrypt.ts","../src/encryption/operations/encrypt-model.ts","../src/encryption/operations/encrypt-query.ts"],"sourcesContent":["import { type Result, withResult } from '@byteslice/result'\nimport { newClient } from '@cipherstash/protect-ffi'\nimport { validate as uuidValidate } from 'uuid'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\n// `LockContext` is imported type-only so the TSDoc {@link} references in the\n// comments below resolve; it is erased at compile time.\nimport type { LockContext } from '@/identity'\nimport {\n buildEncryptConfig,\n type EncryptConfig,\n encryptConfigSchema,\n // Imported type-only for the TSDoc {@link} references in the comments below.\n type encryptedColumn,\n type encryptedField,\n type encryptedTable,\n} from '@/schema'\nimport type {\n AuthStrategy,\n BuildableTable,\n BulkDecryptPayload,\n BulkEncryptPayload,\n Client,\n Encrypted,\n EncryptedFromBuildableTable,\n EncryptionClientConfig,\n EncryptOptions,\n EncryptQueryOptions,\n KeysetIdentifier,\n Plaintext,\n ScalarQueryTerm,\n} from '@/types'\nimport { logger } from '@/utils/logger'\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\n// Re-export the operation classes returned by EncryptionClient methods so they\n// are part of the public API and appear in the generated reference, allowing\n// TSDoc {@link} references and method return types to resolve to real pages.\nexport {\n BatchEncryptQueryOperation,\n BulkDecryptModelsOperation,\n BulkDecryptOperation,\n BulkEncryptModelsOperation,\n BulkEncryptOperation,\n DecryptModelOperation,\n DecryptOperation,\n EncryptModelOperation,\n EncryptOperation,\n EncryptQueryOperation,\n}\n\nexport const noClientError = () =>\n new Error(\n 'The Encryption client has not been initialized. Please call init() before using the client.',\n )\n\n/**\n * Resolve the EQL wire version for a client from its schema set.\n *\n * One FFI client emits exactly one wire format, so the whole schema set must\n * agree. EQL v3 tables (from `@cipherstash/stack/v3`) are detected by their\n * `buildColumnKeyMap()` marker — v2 tables don't have one:\n *\n * - every schema is v3 → `3`;\n * - no schema is v3 → `undefined`, leaving the FFI's v2 default (and its\n * byte-identical v2 output) untouched;\n * - a mix of the two → throws: the v2 tables target `eql_v2_encrypted`\n * columns and the v3 tables target `eql_v3` domains, so no single wire\n * format serves both. Split them across two clients.\n *\n * An explicit `config.eqlVersion` bypasses detection (the wire format is\n * then unambiguous — e.g. writing v2-wire from a v3 schema set during a\n * migration), but a mixed schema set still throws.\n *\n * @internal exported for unit-test coverage of the detection matrix.\n */\nexport function resolveEqlVersion(\n schemas: readonly BuildableTable[],\n explicit?: 2 | 3,\n): 2 | 3 | undefined {\n const v3Count = schemas.filter(\n (schema) => typeof schema.buildColumnKeyMap === 'function',\n ).length\n\n if (v3Count > 0 && v3Count < schemas.length) {\n throw new Error(\n '[encryption]: cannot mix EQL v2 and EQL v3 tables in one client — one client emits exactly one wire format. Create separate clients for the v2 and v3 schemas.',\n )\n }\n\n if (explicit !== undefined) {\n return explicit\n }\n\n return v3Count === 0 ? undefined : 3\n}\n\n/** The EncryptionClient is the main entry point for interacting with the CipherStash Encryption 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\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 authStrategy?: AuthStrategy\n eqlVersion?: 2 | 3\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 Encryption client with the following config:',\n {\n encryptConfig: validated,\n },\n )\n\n // newClient handles env var fallback internally via withEnvCredentials,\n // so we pass config values through without manual fallback here.\n // When `authStrategy` is supplied, protect-ffi invokes its getToken()\n // on every ZeroKMS request instead of building an AutoStrategy\n // from the credentials in clientOpts (the clientKey is still used\n // for encryption). Passing `strategy: undefined` is equivalent to\n // omitting it, so the default credentials path is unaffected.\n // `eqlVersion` selects the wire format `encrypt`/`encryptQuery`\n // emit (protect-ffi 0.27+); `eqlVersion: undefined` is likewise\n // equivalent to omitting it, leaving the FFI's v2 default — and\n // its byte-identical v2 output — untouched.\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 strategy: config.authStrategy,\n eqlVersion: config.eqlVersion,\n })\n\n this.encryptConfig = validated\n\n logger.debug('Successfully initialized the Encryption 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.\n * @param opts - Options specifying the column (or nested field) and table for encryption. See {@link EncryptOptions}.\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 EncryptOptions}\n * @see {@link Result}\n * @see {@link encryptedTable}\n * @see {@link encryptedColumn}\n * @see {@link encryptedField}\n * @see {@link LockContext}\n * @see {@link EncryptOperation}\n */\n encrypt(plaintext: Plaintext, opts: EncryptOptions): 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.\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: Plaintext,\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: Plaintext | readonly ScalarQueryTerm[],\n opts?: EncryptQueryOptions,\n ): EncryptQueryOperation | BatchEncryptQueryOperation {\n // Discriminate between ScalarQueryTerm[] and Plaintext (which can also be an\n // array) using a type guard function. Only route to batch mode when no opts\n // are supplied — an explicit EncryptQueryOptions forces the single-plaintext\n // path even if the plaintext value happens to be an array.\n if (!opts && 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 Plaintext,\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 * @remarks\n * The public input type rejects null, but at runtime `decrypt` will\n * short-circuit and return null when given a null ciphertext\n * (defense in depth for legacy / manually-NULLed DB rows reached via\n * casts or dynamic field walking). The narrow return type holds for\n * any caller that respects the input contract.\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 * The return type is **schema-aware**: fields matching the table schema are\n * typed as `Encrypted`, while other fields retain their original types. For\n * best results, let TypeScript infer the type parameters from the arguments\n * rather than providing an explicit type argument.\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` that can be awaited to get a `Result`\n * containing the model with schema-defined fields typed as `Encrypted`,\n * 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 * // Let TypeScript infer the return type from the schema.\n * // result.data.email is typed as `Encrypted`, result.data.id stays `string`.\n * const result = await client.encryptModel(\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 * console.log(result.data.id) // string\n * console.log(result.data.email) // Encrypted\n * }\n * ```\n */\n encryptModel<T extends Record<string, unknown>, Table extends BuildableTable>(\n input: T,\n table: Table,\n ): EncryptModelOperation<EncryptedFromBuildableTable<T, Table>> {\n return new EncryptModelOperation(\n this.client,\n input as Record<string, unknown>,\n table,\n )\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 * The return type is **schema-aware**: fields matching the table schema are\n * typed as `Encrypted`, while other fields retain their original types. For\n * best results, let TypeScript infer the type parameters from the arguments.\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` that can be awaited to get a `Result`\n * containing an array of models with schema-defined fields typed as `Encrypted`,\n * 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 * // Let TypeScript infer the return type from the schema.\n * // Each item's email is typed as `Encrypted`, id stays `string`.\n * const result = await client.bulkEncryptModels(\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<\n T extends Record<string, unknown>,\n Table extends BuildableTable,\n >(\n input: Array<T>,\n table: Table,\n ): BulkEncryptModelsOperation<EncryptedFromBuildableTable<T, Table>> {\n return new BulkEncryptModelsOperation(\n this.client,\n input as Array<Record<string, unknown>>,\n table,\n )\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.\n *\n * @param plaintexts - An array of objects with `plaintext` (and optional `id`) fields.\n * @param opts - Options specifying the target column (or nested {@link encryptedField}) and table. See {@link EncryptOptions}.\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 * ],\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 /**\n * Get the encrypt config object.\n *\n * @returns The encrypt config object.\n */\n getEncryptConfig(): EncryptConfig | undefined {\n return this.encryptConfig\n }\n}\n\n// Emit the `config.strategy` → `config.authStrategy` rename warning at most\n// once per process so repeated `Encryption()` calls don't spam the console.\nlet warnedStrategyDeprecated = false\nfunction warnStrategyDeprecated(): void {\n if (warnedStrategyDeprecated) return\n warnedStrategyDeprecated = true\n console.warn(\n '[encryption]: `config.strategy` is deprecated and will be removed in a future release — use `config.authStrategy` instead.',\n )\n}\n\n/**\n * Reset the once-per-process deprecation-warning latch. Test-only hook so\n * suites can assert the warning fires deterministically, independent of test\n * ordering. Not re-exported from the package entry, so it stays off the public\n * API surface.\n * @internal\n */\nexport function __resetStrategyDeprecationWarningForTests(): void {\n warnedStrategyDeprecated = false\n}\n\n/**\n * Creates and initializes an Encryption client for encrypting and decrypting data with CipherStash.\n *\n * Provide at least one schema (from {@link encryptedTable}) so the client knows which tables and\n * columns to use:\n *\n * ```typescript\n * import { Encryption, encryptedTable, encryptedColumn } from \"@cipherstash/stack\"\n *\n * const users = encryptedTable(\"users\", { email: encryptedColumn(\"email\") })\n * const client = await Encryption({ schemas: [users] })\n * const result = await client.encrypt(\"alice@example.com\", { column: users.email, table: users })\n * ```\n *\n * ## Authentication\n *\n * The snippets in this section reuse the `users` schema from the example above, and\n * `workspaceCrn` / `accessKey` stand in for your own workspace credentials (from the\n * [dashboard](https://dashboard.cipherstash.com) or the `CS_*` variables below).\n *\n * By default the client uses the `auto` auth strategy. `auto` first looks for the `CS_*`\n * environment variables (see below) and, if they are not set, falls back to the local **dev\n * profile** on your machine. The dev profile also supplies the client key, so during local\n * development you generally don't need to set any environment variables at all.\n *\n * ### Local development — create a dev profile\n *\n * Log in once to create the dev profile that `auto` picks up automatically:\n *\n * ```bash\n * npx stash auth login\n * ```\n *\n * ### Production / CI — environment variables\n *\n * In production and CI you typically authenticate with the four `CS_*` environment variables\n * instead of a dev profile. Developers can obtain these values from the\n * [CipherStash dashboard](https://dashboard.cipherstash.com):\n *\n * | Environment variable | Description |\n * | ---------------------- | ------------------------------------------------------------------------------ |\n * | `CS_WORKSPACE_CRN` | The workspace Cloud Resource Name (CRN) that identifies your workspace. |\n * | `CS_CLIENT_ID` | The client identifier issued when you create an access key. |\n * | `CS_CLIENT_KEY` | The client key material combined with ZeroKMS to perform encryption. |\n * | `CS_CLIENT_ACCESS_KEY` | The API access key used to authenticate requests to CipherStash. |\n *\n * When these are set, `auto` uses them in preference to the local dev profile.\n *\n * ### Custom auth strategies — `config.authStrategy`\n *\n * For finer control, pass an explicit strategy via `config.authStrategy` (from `@cipherstash/auth`,\n * re-exported by `@cipherstash/stack`). See the `@cipherstash/auth` package for the full list. Two\n * common choices:\n *\n * `AccessKeyStrategy` — like `auto`, but only ever uses an access key; it never falls back to the\n * local dev profile. Ideal for services and CI:\n *\n * ```typescript\n * import { Encryption, AccessKeyStrategy } from \"@cipherstash/stack\"\n *\n * const client = await Encryption({\n * schemas: [users],\n * config: {\n * authStrategy: AccessKeyStrategy.create(workspaceCrn, accessKey),\n * },\n * })\n * ```\n *\n * `OidcFederationStrategy` — authenticate end users through your own identity provider (Supabase,\n * Clerk, Auth0 or Okta) by federating their OIDC JWT into a CipherStash token. Add the provider to\n * your workspace first at\n * [dashboard.cipherstash.com/workspaces/_/oidc-providers](https://dashboard.cipherstash.com/workspaces/_/oidc-providers)\n * (the `_` in the URL resolves to whichever workspace you select):\n *\n * ```typescript\n * import { Encryption, OidcFederationStrategy } from \"@cipherstash/stack\"\n *\n * // Authenticate every ZeroKMS request as the signed-in user.\n * const client = await Encryption({\n * schemas: [users],\n * config: {\n * authStrategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()),\n * },\n * })\n * ```\n *\n * ### Lock context (identity-bound encryption)\n *\n * Lock context is an **additional** capability layered on top of `OidcFederationStrategy`: it\n * requires that strategy, but `OidcFederationStrategy` does not require lock context. It binds a\n * value to a claim from the user's JWT (typically `sub`) so that only the user who encrypted a\n * value can decrypt it:\n *\n * ```typescript\n * // Bind the data key to the user's `sub` claim.\n * const result = await client\n * .encrypt(\"alice@example.com\", { column: users.email, table: users })\n * .withLockContext({ identityClaim: [\"sub\"] })\n * ```\n *\n * Because the lock is tied to a specific end user's identity, `AccessKeyStrategy` (which\n * authenticates a service, not a user) is not valid for lock context — there is no user `sub`\n * claim to bind to.\n *\n * ## Keysets (multi-tenant isolation)\n *\n * Pass `config.keyset` to encrypt under a specific **keyset** — a named or UUID-identified keyspace\n * that gives each tenant its own cryptographic isolation, so data encrypted under one keyset cannot\n * be decrypted under another. Create and manage keysets in the\n * [dashboard](https://dashboard.cipherstash.com/workspaces/_/keysets) (the `_` in the URL resolves\n * to whichever workspace you select); omit `config.keyset` to use the workspace's default keyset.\n *\n * ```typescript\n * // `users` is the schema from the first example above.\n * const client = await Encryption({\n * schemas: [users],\n * config: {\n * keyset: { name: \"tenant-a\" }, // or { id: \"<uuid>\" }\n * },\n * })\n * ```\n *\n * A client is bound to a single keyset for its lifetime, so multi-tenant applications use **one\n * `Encryption()` client per tenant**. Keysets are orthogonal to `authStrategy` and lock context —\n * they isolate a whole tenant's *keyspace* (coarse, fixed per client), whereas lock context binds\n * an individual value to a user's identity claim (fine-grained, per operation) — and can be\n * combined with both.\n *\n * @param config - Initialization options. Must include `schemas`; optionally include `config` for\n * credentials and authentication. Logging is configured via the `STASH_STACK_LOG` environment\n * variable (`debug | info | error`, default: `error`).\n * @returns A Promise that resolves to an initialized {@link EncryptionClient} ready for\n * {@link EncryptionClient.encrypt}, {@link EncryptionClient.decrypt}, and related operations.\n *\n * @throws Throws if `schemas` is empty, or if a keyset `id` is supplied but is not a valid UUID.\n * Also throws if the client fails to initialize (e.g. invalid credentials or config).\n *\n * @see {@link EncryptionClientConfig} for full config options.\n * @see {@link ClientConfig.authStrategy} for the auth strategy field.\n * @see {@link EncryptionClient} for available methods after initialization.\n */\nexport const Encryption = async (\n config: EncryptionClientConfig,\n): Promise<EncryptionClient> => {\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 !uuidValidate(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 // Resolve the auth strategy, honouring the deprecated `strategy` alias.\n // Warn whenever the deprecated field is present at all — even alongside\n // `authStrategy` — so the leftover field gets cleaned up. `authStrategy`\n // still wins when both are set.\n if (clientConfig?.strategy) {\n warnStrategyDeprecated()\n }\n const authStrategy = clientConfig?.authStrategy ?? clientConfig?.strategy\n\n const client = new EncryptionClient()\n const encryptConfig = buildEncryptConfig(...schemas)\n\n // Resolve the wire format for this client: an explicit\n // `config.eqlVersion` wins; otherwise it is auto-detected from the\n // schema set (v3 tables → 3, v2 tables → the FFI's v2 default). A mixed\n // v2 + v3 schema set throws — one client emits exactly one wire format.\n const eqlVersion = resolveEqlVersion(schemas, clientConfig?.eqlVersion)\n\n const result = await client.init({\n encryptConfig,\n ...clientConfig,\n authStrategy,\n eqlVersion,\n })\n\n if (result.failure) {\n throw new Error(`[encryption]: ${result.failure.message}`)\n }\n\n return result.data\n}\n","export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;\n","import REGEX from './regex.js';\nfunction validate(uuid) {\n return typeof uuid === 'string' && REGEX.test(uuid);\n}\nexport default validate;\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 { type Result, withResult } from '@byteslice/result'\nimport type {\n Encrypted as CipherStashEncrypted,\n EncryptedQuery as CipherStashEncryptedQuery,\n EncryptedV3Query as CipherStashEncryptedV3Query,\n} from '@cipherstash/protect-ffi'\nimport {\n encryptQueryBulk as ffiEncryptQueryBulk,\n type JsPlaintext,\n type QueryPayload,\n} from '@cipherstash/protect-ffi'\nimport { formatEncryptedResult } from '@/encryption/helpers'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport {\n type Context,\n type LockContextInput,\n resolveLockContext,\n} from '@/identity'\nimport type { Client, EncryptedQueryResult, ScalarQueryTerm } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\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// Separates null/undefined values from non-null terms in the input array\n// so they bypass the FFI call. Original indices are tracked so the\n// reassembled result preserves position.\nfunction filterNullTerms(terms: readonly ScalarQueryTerm[]): {\n nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[]\n} {\n const nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[] = []\n terms.forEach((term, index) => {\n if (term.value !== null && term.value !== undefined) {\n nonNullTerms.push({ term, originalIndex: index })\n }\n })\n return { 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 * Reassembles the result array, slotting null at the original indices of\n * filtered-out terms and formatting encrypted values for non-null terms.\n */\nfunction assembleResults(\n totalLength: number,\n encryptedValues: (\n | CipherStashEncrypted\n | CipherStashEncryptedQuery\n | CipherStashEncryptedV3Query\n )[],\n nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[],\n): EncryptedQueryResult[] {\n const results: EncryptedQueryResult[] = new Array(totalLength).fill(null)\n nonNullTerms.forEach(({ term, originalIndex }, i) => {\n results[originalIndex] = formatEncryptedResult(\n encryptedValues[i],\n term.returnType,\n )\n })\n return results\n}\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: LockContextInput,\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 { 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\nexport class BatchEncryptQueryOperationWithLockContext extends EncryptionOperation<\n EncryptedQueryResult[]\n> {\n constructor(\n private client: Client,\n private terms: readonly ScalarQueryTerm[],\n private lockContext: LockContextInput,\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 const { 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 context = resolveLockContext(this.lockContext)\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 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 {\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 type { QueryOpName } from '@cipherstash/protect-ffi'\nimport type {\n BuildableQueryColumn,\n FfiIndexTypeName,\n Plaintext,\n QueryTypeName,\n} 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: BuildableQueryColumn): 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: Plaintext): QueryOpName {\n if (typeof plaintext === 'string') {\n return 'ste_vec_selector'\n }\n // Objects (incl. Date), arrays, numbers, booleans are all valid JSONB\n // containment values\n if (\n typeof plaintext === 'object' ||\n typeof plaintext === 'number' ||\n typeof plaintext === 'boolean'\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: BuildableQueryColumn,\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 * v3-only: an order-capable column answers EQUALITY via its `ore` (`ob`) index.\n *\n * The v3 capability contract (`src/eql/v3`) documents `equality` as \"exact-match\n * lookups (EQL `hm`, or comparison via `ob`)\", so an order-capable column with only\n * an `ore` index still supports equality — the equality-vs-range distinction is made\n * by the SQL comparison operator (`=` vs `>=`), NOT by the ciphertext (the FFI emits\n * the same `ob` term either way). The default `equality → unique` mapping would\n * wrongly reject these columns.\n *\n * Gated on `getQueryCapabilities`, which only v3 queryable columns expose — a v2\n * `EncryptedColumn` lacks it and so never matches, preserving v2's\n * equality-without-unique throw unchanged (the no-v2-change constraint).\n */\nfunction resolvesEqualityViaOre(column: BuildableQueryColumn): boolean {\n if (!('getQueryCapabilities' in column)) return false\n if (!column.getQueryCapabilities().equality) return false\n const indexes = column.build().indexes ?? {}\n return !indexes.unique && !!indexes.ore\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: BuildableQueryColumn,\n queryType?: QueryTypeName,\n plaintext?: Plaintext | null,\n): { indexType: FfiIndexTypeName; queryOp?: QueryOpName } {\n const indexType = queryType\n ? queryTypeToFfi[queryType]\n : inferIndexType(column)\n\n if (queryType) {\n // An order-capable v3 column answers equality via its `ore` index (`ob`\n // term) — the same term `orderAndRange` emits, distinguished only by the SQL\n // `=` operator. Resolve to `ore` (queryOp undefined) instead of throwing on\n // the missing `unique` index. v2 columns never enter here (see helper).\n if (queryType === 'equality' && resolvesEqualityViaOre(column)) {\n return { indexType: 'ore' }\n }\n\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 { Result } from '@byteslice/result'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { FfiIndexTypeName } from '@/types'\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 { Result } from '@byteslice/result'\nimport type { EncryptionError } from '@/errors'\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 { type Result, withResult } from '@byteslice/result'\nimport {\n type Encrypted as CipherStashEncrypted,\n type DecryptResult,\n decryptBulkFallible,\n} from '@cipherstash/protect-ffi'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport {\n type Context,\n type LockContextInput,\n resolveLockContext,\n} from '@/identity'\nimport type { BulkDecryptedData, BulkDecryptPayload, Client } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n// Drops nulls so they don't reach protect-ffi's bulk decrypt. The\n// dropped positions are re-inserted as null in `mapDecryptedDataToResult`.\nconst createDecryptPayloads = (\n encryptedPayloads: BulkDecryptPayload,\n lockContext?: Context,\n) => {\n return encryptedPayloads\n .filter(({ data }) => data !== null)\n .map(({ id, data }) => ({\n id,\n ciphertext: data as CipherStashEncrypted,\n ...(lockContext && { lockContext }),\n }))\n}\n\nconst createNullResult = (\n encryptedPayloads: BulkDecryptPayload,\n): BulkDecryptedData => encryptedPayloads.map(({ id }) => ({ id, data: null }))\n\nconst mapDecryptedDataToResult = (\n encryptedPayloads: BulkDecryptPayload,\n decryptedData: DecryptResult[],\n): BulkDecryptedData => {\n const result: BulkDecryptedData = new Array(encryptedPayloads.length)\n let decryptedIndex = 0\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] = { id: encryptedPayloads[i].id, error: decryptResult.error }\n } else {\n result[i] = { id: encryptedPayloads[i].id, data: decryptResult.data }\n }\n decryptedIndex++\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: LockContextInput,\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: LockContextInput\n\n constructor(operation: BulkDecryptOperation, lockContext: LockContextInput) {\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 lockContext = resolveLockContext(this.lockContext)\n\n const nonNullPayloads = createDecryptPayloads(\n encryptedPayloads,\n lockContext,\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 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 {\n type Encrypted as CipherStashEncrypted,\n decryptBulk,\n encryptBulk,\n} from '@cipherstash/protect-ffi'\nimport { isEncryptedPayload } from '@/encryption/helpers'\nimport type { AuditData } from '@/encryption/operations/base-operation'\nimport type { Context } from '@/identity'\nimport type { BuildableTable, Client, Decrypted, Encrypted } from '@/types'\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 */\n/**\n * Resolve how a table's model fields map onto encrypt-config columns.\n *\n * `columnPaths` are the keys used to MATCH a user model's fields (the JS\n * property names); `toColumnName` maps a matched field to the name the FFI /\n * encrypt config is keyed by (the DB name).\n *\n * When a table exposes `buildColumnKeyMap()` (v3), those two can differ, so we\n * match by property but address by DB name. Otherwise (v2) `build()` already\n * keys columns by the property name, so both are that same key (identity map).\n */\nexport function resolveEncryptColumnMap(table: BuildableTable): {\n columnPaths: string[]\n toColumnName: (path: string) => string\n} {\n const keyMap = table.buildColumnKeyMap?.()\n if (keyMap) {\n return {\n columnPaths: Object.keys(keyMap),\n toColumnName: (path) => keyMap[path] ?? path,\n }\n }\n const columnPaths = Object.keys(table.build().columns)\n return { columnPaths, toColumnName: (path) => path }\n}\n\nfunction prepareFieldsForEncryption<T extends Record<string, unknown>>(\n model: T,\n table: BuildableTable,\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 (matched by JS property name).\n const { columnPaths } = resolveEncryptColumnMap(table)\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(\n model: Record<string, unknown>,\n table: BuildableTable,\n client: Client,\n auditData?: AuditData,\n): Promise<Record<string, unknown>> {\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 { toColumnName } = resolveEncryptColumnMap(table)\n const bulkEncryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n plaintext: value as string,\n table: table.tableName,\n column: toColumnName(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\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: Context,\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,\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 with lock context\n */\nexport async function encryptModelFieldsWithLockContext(\n model: Record<string, unknown>,\n table: BuildableTable,\n client: Client,\n lockContext: Context,\n auditData?: AuditData,\n): Promise<Record<string, unknown>> {\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 { toColumnName } = resolveEncryptColumnMap(table)\n const bulkEncryptPayload = Object.entries(operationFields).map(\n ([key, value]) => ({\n id: key,\n plaintext: value as string,\n table: table.tableName,\n column: toColumnName(key),\n lockContext,\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\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?: BuildableTable,\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 (matched by JS property name).\n const { columnPaths } = resolveEncryptColumnMap(table)\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 * Collect the per-model fields out of a bulk-operation result map keyed by\n * `${modelIndex}-${fieldKey}` ids, splitting each id at the FIRST hyphen\n * only. Field keys may themselves contain hyphens (a `some-field` column, or\n * a nested `profile.some-field` path), so a naive `split('-')` would truncate\n * the field key at its first hyphen and silently drop the value during model\n * reconstruction.\n */\nfunction fieldsForModelIndex(\n fields: Record<string, unknown>,\n modelIndex: number,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [id, value] of Object.entries(fields)) {\n const sep = id.indexOf('-')\n if (Number.parseInt(id.slice(0, sep), 10) !== modelIndex) continue\n result[id.slice(sep + 1)] = value\n }\n return result\n}\n\n/**\n * Helper function to convert multiple decrypted models to models with encrypted fields\n */\nexport async function bulkEncryptModels(\n models: Record<string, unknown>[],\n table: BuildableTable,\n client: Client,\n auditData?: AuditData,\n): Promise<Record<string, unknown>[]> {\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 { toColumnName } = resolveEncryptColumnMap(table)\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: toColumnName(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 = fieldsForModelIndex(encryptedData, modelIndex)\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\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 = fieldsForModelIndex(decryptedFields, modelIndex)\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: Context,\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,\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 // 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 = fieldsForModelIndex(decryptedFields, modelIndex)\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 models: Record<string, unknown>[],\n table: BuildableTable,\n client: Client,\n lockContext: Context,\n auditData?: AuditData,\n): Promise<Record<string, unknown>[]> {\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 { toColumnName } = resolveEncryptColumnMap(table)\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: toColumnName(key),\n lockContext,\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 // 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 = fieldsForModelIndex(encryptedData, modelIndex)\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\n })\n}\n","import { type Result, withResult } from '@byteslice/result'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport {\n bulkDecryptModels,\n bulkDecryptModelsWithLockContext,\n} from '../helpers/model-helpers'\nimport { noClientError } from '../index'\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: LockContextInput,\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: LockContextInput\n\n constructor(\n operation: BulkDecryptModelsOperation<T>,\n lockContext: LockContextInput,\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 = resolveLockContext(this.lockContext)\n\n const auditData = this.getAuditData()\n\n return await bulkDecryptModelsWithLockContext<T>(\n models,\n client,\n context,\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 Result, withResult } from '@byteslice/result'\nimport { encryptBulk, type JsPlaintext } from '@cipherstash/protect-ffi'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport {\n type Context,\n type LockContextInput,\n resolveLockContext,\n} from '@/identity'\nimport type {\n BuildableColumn,\n BuildableTable,\n BulkEncryptedData,\n BulkEncryptPayload,\n Client,\n Encrypted,\n EncryptOptions,\n} from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\n// Drops nulls so they don't reach protect-ffi (which would otherwise\n// produce a SteVec wrapping the JSON null). The dropped positions are\n// re-inserted as null in `mapEncryptedDataToResult`.\nconst createEncryptPayloads = (\n plaintexts: BulkEncryptPayload,\n column: BuildableColumn,\n table: BuildableTable,\n lockContext?: Context,\n) => {\n return plaintexts\n .filter(({ plaintext }) => plaintext !== null)\n .map(({ id, plaintext }) => ({\n id,\n plaintext: plaintext as JsPlaintext,\n column: column.getName(),\n table: table.tableName,\n ...(lockContext && { lockContext }),\n }))\n}\n\nconst createNullResult = (plaintexts: BulkEncryptPayload): BulkEncryptedData =>\n plaintexts.map(({ id }) => ({ id, data: null }))\n\nconst mapEncryptedDataToResult = (\n plaintexts: BulkEncryptPayload,\n encryptedData: Encrypted[],\n): BulkEncryptedData => {\n const result: BulkEncryptedData = new Array(plaintexts.length)\n let encryptedIndex = 0\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] = { id: plaintexts[i].id, data: encryptedData[encryptedIndex] }\n encryptedIndex++\n }\n }\n return result\n}\n\nexport class BulkEncryptOperation extends EncryptionOperation<BulkEncryptedData> {\n private client: Client\n private plaintexts: BulkEncryptPayload\n private column: BuildableColumn\n private table: BuildableTable\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: LockContextInput,\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: BuildableColumn\n table: BuildableTable\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: LockContextInput\n\n constructor(operation: BulkEncryptOperation, lockContext: LockContextInput) {\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 } = 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 lockContext = resolveLockContext(this.lockContext)\n\n const nonNullPayloads = createEncryptPayloads(\n plaintexts,\n column,\n table,\n lockContext,\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 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 { type Result, withResult } from '@byteslice/result'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type { BuildableTable, Client } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport {\n bulkEncryptModels,\n bulkEncryptModelsWithLockContext,\n} from '../helpers/model-helpers'\nimport { noClientError } from '../index'\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: Record<string, unknown>[]\n private table: BuildableTable\n\n constructor(\n client: Client,\n models: Record<string, unknown>[],\n table: BuildableTable,\n ) {\n super()\n this.client = client\n this.models = models\n this.table = table\n }\n\n public withLockContext(\n lockContext: LockContextInput,\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(\n this.models,\n this.table,\n this.client,\n auditData,\n )) as T[]\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: Record<string, unknown>[]\n table: BuildableTable\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: LockContextInput\n\n constructor(\n operation: BulkEncryptModelsOperation<T>,\n lockContext: LockContextInput,\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 = resolveLockContext(this.lockContext)\n\n const auditData = this.getAuditData()\n\n return (await bulkEncryptModelsWithLockContext(\n models,\n table,\n client,\n context,\n auditData,\n )) as T[]\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 Result, withResult } from '@byteslice/result'\nimport {\n decrypt as ffiDecrypt,\n type JsPlaintext,\n} from '@cipherstash/protect-ffi'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type { Client, Encrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\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> {\n private client: Client\n // Internally widened to allow null so the runtime guard below can\n // short-circuit on legacy / manually-NULLed rows. The public\n // `Encryption.decrypt()` signature still rejects null at the type\n // layer; this is defense in depth for direct construction.\n private encryptedData: Encrypted | null\n\n constructor(client: Client, encryptedData: Encrypted | null) {\n super()\n this.client = client\n this.encryptedData = encryptedData\n }\n\n public withLockContext(\n lockContext: LockContextInput,\n ): DecryptOperationWithLockContext {\n return new DecryptOperationWithLockContext(this, lockContext)\n }\n\n public async execute(): Promise<Result<JsPlaintext, 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 // See encrypt.ts for the same defense-in-depth pattern.\n return null as unknown as JsPlaintext\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 | null\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> {\n private operation: DecryptOperation\n private lockContext: LockContextInput\n\n constructor(operation: DecryptOperation, lockContext: LockContextInput) {\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, 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 as unknown as JsPlaintext\n }\n\n const { metadata } = this.getAuditData()\n\n const lockContext = resolveLockContext(this.lockContext)\n\n return await ffiDecrypt(client, {\n ciphertext: encryptedData,\n unverifiedContext: metadata,\n lockContext,\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 Result, withResult } from '@byteslice/result'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type { Client, Decrypted } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport {\n decryptModelFields,\n decryptModelFieldsWithLockContext,\n} from '../helpers/model-helpers'\nimport { noClientError } from '../index'\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: LockContextInput,\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: LockContextInput\n\n constructor(\n operation: DecryptModelOperation<T>,\n lockContext: LockContextInput,\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 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 = resolveLockContext(this.lockContext)\n\n const auditData = this.getAuditData()\n\n return await decryptModelFieldsWithLockContext<T>(\n model,\n client,\n context,\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 Result, withResult } from '@byteslice/result'\nimport {\n encrypt as ffiEncrypt,\n type JsPlaintext,\n} from '@cipherstash/protect-ffi'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { assertValidNumericValue } from '@/encryption/helpers/validation'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type {\n BuildableColumn,\n BuildableTable,\n Client,\n Encrypted,\n EncryptOptions,\n Plaintext,\n} from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport { noClientError } from '../index'\nimport { EncryptionOperation } from './base-operation'\n\nexport class EncryptOperation extends EncryptionOperation<Encrypted> {\n private client: Client\n // Internally widened to allow null so the runtime guard below can\n // short-circuit. The public `Encryption.encrypt()` signature still\n // rejects null at the type layer; this is defense in depth for callers\n // that reach this class through casts or dynamic field walking.\n private plaintext: Plaintext | null\n private column: BuildableColumn\n private table: BuildableTable\n\n constructor(\n client: Client,\n plaintext: Plaintext | 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: LockContextInput,\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 // Defense in depth: the public `Encryption.encrypt()` signature\n // rejects null, but null can still arrive here via casts or\n // dynamic field walking. Return null directly so the result\n // matches DB NULL semantics rather than encrypting JSON null\n // into a SteVec. The cast acknowledges the type-narrow\n // contract at the public boundary.\n return null as unknown as Encrypted\n }\n\n assertValidNumericValue(this.plaintext)\n\n const { metadata } = this.getAuditData()\n\n return await ffiEncrypt(this.client, {\n // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via\n // `toJSON` at the boundary); cast until the upstream `JsPlaintext` input\n // union is corrected to include it.\n plaintext: this.plaintext as JsPlaintext,\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: Plaintext | null\n column: BuildableColumn\n table: BuildableTable\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: LockContextInput\n\n constructor(operation: EncryptOperation, lockContext: LockContextInput) {\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 } = 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 as unknown as Encrypted\n }\n\n assertValidNumericValue(plaintext)\n\n const { metadata } = this.getAuditData()\n const lockContext = resolveLockContext(this.lockContext)\n\n return await ffiEncrypt(client, {\n plaintext: plaintext as JsPlaintext,\n column: column.getName(),\n table: table.tableName,\n lockContext,\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 { type Result, withResult } from '@byteslice/result'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type { BuildableTable, Client } from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\nimport {\n encryptModelFields,\n encryptModelFieldsWithLockContext,\n} from '../helpers/model-helpers'\nimport { noClientError } from '../index'\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: Record<string, unknown>\n private table: BuildableTable\n\n constructor(\n client: Client,\n model: Record<string, unknown>,\n table: BuildableTable,\n ) {\n super()\n this.client = client\n this.model = model\n this.table = table\n }\n\n public withLockContext(\n lockContext: LockContextInput,\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(\n this.model,\n this.table,\n this.client,\n auditData,\n )) as T\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: Record<string, unknown>\n table: BuildableTable\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: LockContextInput\n\n constructor(\n operation: EncryptModelOperation<T>,\n lockContext: LockContextInput,\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, 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 = resolveLockContext(this.lockContext)\n\n const auditData = this.getAuditData()\n\n return (await encryptModelFieldsWithLockContext(\n model,\n table,\n client,\n context,\n auditData,\n )) as T\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 Result, withResult } from '@byteslice/result'\nimport {\n encryptQuery as ffiEncryptQuery,\n type JsPlaintext,\n} from '@cipherstash/protect-ffi'\nimport { formatEncryptedResult } from '@/encryption/helpers'\nimport { getErrorCode } from '@/encryption/helpers/error-code'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport { type LockContextInput, resolveLockContext } from '@/identity'\nimport type {\n Client,\n EncryptedQueryResult,\n EncryptQueryOptions,\n Plaintext,\n} from '@/types'\nimport { createRequestLogger } from '@/utils/logger'\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\nexport class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryResult> {\n constructor(\n private client: Client,\n private plaintext: Plaintext | null | undefined,\n private opts: EncryptQueryOptions,\n ) {\n super()\n }\n\n public withLockContext(\n lockContext: LockContextInput,\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<\n Result<EncryptedQueryResult, EncryptionError>\n > {\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 plaintext: Plaintext = this.plaintext\n\n const validationError = validateNumericValue(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 plaintext,\n )\n\n // Validate value/index compatibility\n assertValueIndexCompatibility(\n plaintext,\n indexType,\n this.opts.column.getName(),\n )\n\n const encrypted = await ffiEncryptQuery(this.client, {\n // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via\n // `toJSON` at the boundary); cast until the upstream input union is\n // corrected to include it.\n plaintext: 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\nexport class EncryptQueryOperationWithLockContext extends EncryptionOperation<EncryptedQueryResult> {\n constructor(\n private client: Client,\n private plaintext: Plaintext | null | undefined,\n private opts: EncryptQueryOptions,\n private lockContext: LockContextInput,\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: '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 plaintext: Plaintext = this.plaintext\n\n const validationError = validateNumericValue(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 context = resolveLockContext(this.lockContext)\n\n const { metadata } = this.getAuditData()\n\n const { indexType, queryOp } = resolveIndexType(\n this.opts.column,\n this.opts.queryType,\n plaintext,\n )\n\n // Validate value/index compatibility\n assertValueIndexCompatibility(\n plaintext,\n indexType,\n this.opts.column.getName(),\n )\n\n const encrypted = await ffiEncryptQuery(this.client, {\n // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via\n // `toJSON` at the boundary); cast until the upstream input union is\n // corrected to include it.\n plaintext: plaintext as JsPlaintext,\n column: this.opts.column.getName(),\n table: this.opts.table.tableName,\n indexType,\n queryOp,\n lockContext: context,\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"],"mappings":"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","names":["columnPaths","encryptBulk","createNullResult","encryptBulk"]}
@@ -25,4 +25,4 @@ export {
25
25
  queryTypeToFfi,
26
26
  queryTypeToQueryOp
27
27
  };
28
- //# sourceMappingURL=chunk-MD6742R6.js.map
28
+ //# sourceMappingURL=chunk-4AVL4VZD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n AuthStrategy,\n Encrypted as CipherStashEncrypted,\n EncryptedPayload as CipherStashEncryptedPayload,\n EncryptedQuery as CipherStashEncryptedQuery,\n EncryptedV3Query as CipherStashEncryptedV3Query,\n JsPlaintext,\n newClient,\n QueryOpName,\n} from '@cipherstash/protect-ffi'\nimport type {\n ColumnSchema,\n EncryptedColumn,\n EncryptedField,\n EncryptedTableColumn,\n // Imported type-only for the TSDoc {@link} references in the comments below.\n encryptedColumn,\n encryptedField,\n} from '@/schema'\n\n/**\n * A pluggable authentication strategy for ZeroKMS requests. Any object\n * with a `getToken(): Promise<{ token: string }>` method satisfies it —\n * notably the strategies from `@cipherstash/auth`: `OidcFederationStrategy`\n * (per-user, identity-bound encryption) and `AccessKeyStrategy`\n * (service-to-service / CI). When supplied to {@link ClientConfig.authStrategy},\n * `getToken()` is invoked on every ZeroKMS request, taking precedence over\n * the default `auto` strategy.\n *\n * @see ClientConfig.authStrategy\n */\nexport type { AuthStrategy }\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'>\n\n/** Structural type representing encrypted data stored in the database. Always\n * carries a ciphertext. Covers BOTH wire formats: the EQL v2.3 payloads\n * (`k: \"ct\"` / `k: \"sv\"`) and the EQL v3 payloads (flat `{v: 3, i, c, …}`\n * scalars and `{v: 3, k: \"sv\", i, sv}` SteVec documents). Which format\n * `encrypt` produces is selected by the client's\n * {@link ClientConfig.eqlVersion}; `decrypt` accepts both regardless.\n * v3 scalars carry no `k` discriminator, so narrow with `'k' in payload`\n * before reading it. See also `EncryptedValue` for branded nominal typing,\n * and {@link EncryptedQuery} for the search-term shape returned by\n * `encryptQuery`. */\nexport type Encrypted = CipherStashEncryptedPayload\n\n/** Structural type representing an encrypted query term (search needle)\n * returned by `encryptQuery` / `encryptQueryBulk` for scalar\n * (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path\n * queries, plus — under `eqlVersion: 3` — the `eql_v3.jsonb_query`\n * containment needle. Carries no ciphertext — matched against stored\n * values, never decrypted. v2 JSON containment queries (`ste_vec_term`)\n * return a storage-shaped {@link Encrypted} payload instead. */\nexport type EncryptedQuery =\n | CipherStashEncryptedQuery\n | CipherStashEncryptedV3Query\n\n/**\n * Plaintext values the SDK accepts for encryption.\n *\n * Widens the FFI's `JsPlaintext` (`string | number | boolean |\n * Record<string, unknown> | JsPlaintext[]`) with `Date`. `Date` is a supported\n * cast target that is omitted from the FFI's `JsPlaintext` INPUT union, but it\n * serializes at the boundary via `toJSON` (ISO string), so it is accepted on the\n * way in.\n *\n * `bigint` is intentionally NOT included: the native `@cipherstash/protect-ffi`\n * build cannot marshal a JS `bigint` (V8 throws \"Do not know how to serialize a\n * BigInt\") and rejects a `string` for a `big_int` column. The v3 int8 domains\n * are therefore omitted from the SDK entirely (see `eql/v3`) until the FFI\n * supports lossless bigint I/O; `bigint` returns here alongside them.\n *\n * When the upstream FFI `JsPlaintext` is corrected to include `Date`, the `Date`\n * arm can collapse back into `JsPlaintext`.\n */\nexport type Plaintext = JsPlaintext | Date\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 */\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\n * [dashboard](https://dashboard.cipherstash.com/workspaces/_/keysets); omit to\n * use the workspace's default keyset. A client is bound to one keyset for its\n * lifetime, so use one client per tenant.\n *\n * @see {@link Encryption} for the full keysets walkthrough.\n */\n keyset?: KeysetIdentifier\n\n /**\n * An optional authentication strategy for ZeroKMS requests, from\n * `@cipherstash/auth` (re-exported by `@cipherstash/stack`). When provided,\n * its `getToken()` is invoked on every ZeroKMS request and takes precedence\n * over the default `auto` strategy (the `clientKey` is still required for\n * encryption). Use:\n *\n * - `OidcFederationStrategy` for per-user, identity-bound encryption —\n * federates an end user's OIDC JWT into a CTS service token, so requests\n * authenticate as that user. Pair with `.withLockContext({ identityClaim })`\n * to bind the data key to a claim. This replaces the older\n * `LockContext.identify()` ceremony.\n * - `AccessKeyStrategy` for service-to-service / CI, or any custom\n * `{ getToken() }` object for bespoke token acquisition / caching.\n *\n * Leave unset to use the default `auto` strategy, which reads credentials\n * from the `CS_*` environment variables and falls back to the local dev\n * profile created by `npx stash auth login`.\n *\n * @see {@link AuthStrategy}\n * @see {@link Encryption} for a full walkthrough of the authentication options.\n */\n authStrategy?: AuthStrategy\n\n /**\n * @deprecated Renamed to {@link ClientConfig.authStrategy}. Still honoured for\n * backwards compatibility — passing it logs a deprecation warning at runtime —\n * but it will be removed in a future release. Set `authStrategy` instead.\n */\n strategy?: AuthStrategy\n\n /**\n * The EQL wire version the client emits — one FFI client always emits\n * exactly one wire format.\n *\n * - `2` (the protect-ffi default): payloads target the\n * `eql_v2_encrypted` column type.\n * - `3`: payloads target the per-capability `eql_v3` domains\n * (`eql_v3.text_eq`, `eql_v3.integer_ord_ore`, `eql_v3.json`, …),\n * derived from each column's `cast_as` and indexes.\n *\n * When omitted, {@link Encryption} auto-detects from the schema set:\n * EQL v3 tables (from `@cipherstash/stack/v3`, marked by\n * `buildColumnKeyMap()`) select `3`; v2 tables leave the FFI default\n * (`2`) untouched. Mixing v2 and v3 tables in one client is an error —\n * split them across two clients instead.\n *\n * `decrypt` accepts BOTH formats regardless of this setting, so v2 and\n * v3 data can coexist during a migration.\n *\n * v3 limitation (protect-ffi 0.27): `encryptQuery` supports only JSON\n * containment queries — scalar-index and selector queries throw\n * `EQL_V3_QUERY_UNSUPPORTED` until a v3 scalar query wire shape exists.\n */\n eqlVersion?: 2 | 3\n}\n\ntype AtLeastOneCsTable<T> = [T, ...T[]]\n\n/** Structural contract for a column builder the client can consume for STORAGE\n * (`encrypt`). Satisfied by v2 `EncryptedColumn` / `EncryptedField` AND v3\n * `EncryptedTextSearchColumn` — fields ARE encryptable, so this stays wide. */\nexport interface BuildableColumn {\n getName(): string\n build(): ColumnSchema\n}\n\n/** Structural contract for a column the client can consume for QUERIES\n * (`encryptQuery` / search terms). Narrower than `BuildableColumn`: it must\n * EXCLUDE non-queryable `EncryptedField` (a field has no indexes). A v2\n * `EncryptedColumn` qualifies via the nominal arm; a v3 queryable concrete\n * type qualifies via the `getEqlType()` structural arm; `EncryptedField` (no\n * `getEqlType`, not an `EncryptedColumn`) is rejected. */\nexport interface BuildableV3QueryableColumn extends BuildableColumn {\n getEqlType(): string\n getQueryCapabilities(): {\n equality: boolean\n orderAndRange: boolean\n freeTextSearch: boolean\n }\n isQueryable(): true\n}\n\nexport type BuildableQueryColumn = EncryptedColumn | BuildableV3QueryableColumn\n\n/** Structural contract for a table builder the client can consume. Satisfied by\n * v2 and v3 `EncryptedTable` alike. */\nexport interface BuildableTable {\n tableName: string\n build(): { tableName: string; columns: Record<string, ColumnSchema> }\n /**\n * Optional map from a model field's JS property name to its encrypt-config\n * column name (the DB name). Present when the two can differ — v3 tables key\n * their config by DB name (`column.getName()`) while models are written with\n * JS property keys, so the model path must match by property but address the\n * FFI/config by DB name.\n *\n * Absent on v2 tables, whose `build()` already keys columns by the JS property\n * name; the model path then matches and addresses by that same key.\n */\n buildColumnKeyMap?(): Record<string, string>\n}\n\nexport type EncryptionClientConfig = {\n schemas: AtLeastOneCsTable<BuildableTable>\n config?: ClientConfig\n}\n\n/**\n * The literal column map of a buildable table, read from its type-level\n * `_columnType` brand. Both v2 and v3 `EncryptedTable` carry this brand, so this\n * recovers the literal column keys structurally.\n *\n * This deliberately uses the `_columnType` brand rather than `build().columns`:\n * `BuildableTable.build()` is typed to return `Record<string, ColumnSchema>`,\n * which erases the literal keys and would mark EVERY model field as encrypted.\n *\n * The fallbacks resolve to `Record<never, never>` (a no-key type), NOT `never`:\n * a value typed as the bare structural `BuildableTable` carries no `_columnType`\n * brand, and `keyof never` is `string | number | symbol` — which would wrongly\n * mark EVERY model field as encrypted. `keyof Record<never, never>` is `never`,\n * so `EncryptedFromBuildableTable` degrades gracefully to the model unchanged.\n */\nexport type BuildableTableColumns<T extends BuildableTable> = T extends {\n readonly _columnType: infer C\n}\n ? C extends Record<string, unknown>\n ? C\n : Record<never, never>\n : Record<never, never>\n\n/**\n * Maps a plaintext model type to its encrypted form using a buildable table.\n *\n * Fields whose keys match a column defined in `Table` (via its `_columnType`\n * brand) become `Encrypted` (`Encrypted | null` when the source field is\n * nullable); all other fields retain their original types from `T`. Works for\n * both v2 and v3 tables. See {@link EncryptedFromSchema} for the v2-specific\n * variant retained for backward compatibility.\n */\nexport type EncryptedFromBuildableTable<T, Table extends BuildableTable> = {\n [K in keyof T]: [K] extends [keyof BuildableTableColumns<Table>]\n ? null extends T[K]\n ? Encrypted | null\n : Encrypted\n : T[K]\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt operation options and results\n// ---------------------------------------------------------------------------\n\n/**\n * Options for single-value encrypt operations.\n * Use a column from your table schema (from {@link encryptedColumn}) or a nested\n * field (from {@link encryptedField}) as the target for encryption.\n */\nexport type EncryptOptions = {\n /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */\n column: BuildableColumn // storage: fields are encryptable, so stays wide\n table: BuildableTable\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: Plaintext\n column: BuildableQueryColumn // query: excludes non-queryable EncryptedField\n table: BuildableTable\n returnType?: EncryptedReturnType\n}\n\n/** Encrypted search term result. `eql` return type yields either a storage\n * payload (`Encrypted`, for `ste_vec_term`) or a query-only term\n * (`EncryptedQuery`, for scalar lookups and `ste_vec_selector`); the\n * `composite-literal` return types yield a string. */\nexport type EncryptedSearchTerm = Encrypted | EncryptedQuery | string\n\n/** Result of encryptQuery (single or batch). `eql` return type yields either a\n * storage payload (`Encrypted`) or a query-only term (`EncryptedQuery`); the\n * `composite-literal` return types yield a string. */\n// null elements appear in the batch path when a term has a null/undefined\n// value — the operation preserves position so callers can correlate results\n// with their input array.\nexport type EncryptedQueryResult = Encrypted | EncryptedQuery | string | null\n\n// ---------------------------------------------------------------------------\n// Model field types (encrypted vs decrypted views)\n// ---------------------------------------------------------------------------\n\nexport type EncryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K]\n}\n\nexport type OtherFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K]\n}\n\nexport type DecryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted\n ? K\n : never]: null extends T[K] ? string | null : string\n}\n\n/** Model with encrypted fields replaced by plaintext (decrypted) values */\nexport type Decrypted<T> = OtherFields<T> & DecryptedFields<T>\n\n/**\n * Maps a plaintext model type to its encrypted form using the table schema.\n *\n * Fields whose keys match columns defined in `S` become `Encrypted`;\n * all other fields retain their original types from `T`.\n *\n * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an\n * explicit `<User>` type argument without specifying `S`), the type degrades\n * gracefully to `T` — preserving backward compatibility.\n *\n * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)\n * @typeParam S - The table schema column definition, inferred from the `table` argument\n *\n * @example\n * ```typescript\n * type User = { id: string; email: string }\n * // With a schema that defines `email`:\n * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>\n * // => { id: string; email: Encrypted }\n * ```\n */\nexport type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {\n [K in keyof T]: [K] extends [keyof S]\n ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField]\n ? null extends T[K]\n ? Encrypted | null\n : Encrypted\n : T[K]\n : T[K]\n}\n\n// ---------------------------------------------------------------------------\n// Bulk operations\n// ---------------------------------------------------------------------------\n\n// Bulk payloads admit null elements — bulk operations pass them through\n// untouched (encrypt(null) -> null, decrypt(null) -> null) so callers can\n// process mixed nullable arrays without filtering ahead of time. The\n// runtime guards in the operation classes preserve the null in the\n// position-stable output.\nexport type BulkEncryptPayload = Array<{\n id?: string\n plaintext: Plaintext | null\n}>\n\nexport type BulkEncryptedData = Array<{ id?: string; data: Encrypted | null }>\nexport type BulkDecryptPayload = Array<{ id?: string; data: Encrypted | null }>\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/stack/cipherstash/encryption/searchable-encryption)\n * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\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: BuildableQueryColumn // query: excludes non-queryable EncryptedField\n table: BuildableTable\n queryType?: QueryTypeName\n returnType?: EncryptedReturnType\n}\n\nexport type EncryptQueryOptions = QueryTermBase\n\nexport type ScalarQueryTerm = QueryTermBase & {\n value: Plaintext\n}\n"],"mappings":";AAsbO,IAAM,aAAa;AAAA,EACxB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAGO,IAAM,iBAA0D;AAAA,EACrE,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAGO,IAAM,qBAAkE;AAAA,EAC7E,gBAAgB;AAAA,EAChB,YAAY;AACd;","names":[]}
@@ -58,4 +58,4 @@ export {
58
58
  toFfiKeysetIdentifier,
59
59
  isEncryptedPayload
60
60
  };
61
- //# sourceMappingURL=chunk-4RNBI3UH.js.map
61
+ //# sourceMappingURL=chunk-BNO32ZMV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/encryption/helpers/index.ts"],"sourcesContent":["import type {\n Encrypted as CipherStashEncrypted,\n EncryptedQuery as CipherStashEncryptedQuery,\n EncryptedV3Query as CipherStashEncryptedV3Query,\n KeysetIdentifier as KeysetIdentifierFfi,\n} from '@cipherstash/protect-ffi'\nimport type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types'\n\n/**\n * The shape `encryptQuery` / `encryptQueryBulk` can return: a full storage\n * payload (returned for v2 `ste_vec_term` containment queries), a query-only\n * payload with no ciphertext (scalar `unique`/`match`/`ore` lookups and\n * `ste_vec_selector` path queries), or — under `eqlVersion: 3` — the\n * `eql_v3.jsonb_query` containment needle.\n *\n * TODO: duplicated in `@cipherstash/protect` — see\n * `packages/protect/src/helpers/index.ts`. Both copies should be removed once\n * `@cipherstash/protect-ffi` exports a named alias for the `encryptQuery`\n * return type (https://github.com/cipherstash/stack/pull/473).\n */\ntype EncryptedQueryTerm =\n | CipherStashEncrypted\n | CipherStashEncryptedQuery\n | CipherStashEncryptedV3Query\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: EncryptedQueryTerm): string {\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: EncryptedQueryTerm,\n): string {\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: EncryptedQueryTerm,\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 buildNestedObject,\n parseJsonbPath,\n toJsonPath,\n} from './jsonb'\n"],"mappings":";AAiCO,SAAS,uBAAuB,KAAsC;AAC3E,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAYO,SAAS,4BAA4B,KAAiC;AAC3E,SAAO,IAAI,KAAK,UAAU,KAAK,UAAU,GAAG,CAAC,CAAC;AAChD;AAWO,SAAS,mCACd,KACQ;AACR,SAAO,KAAK,UAAU,4BAA4B,GAAG,CAAC;AACxD;AASO,SAAS,sBACd,WACA,YACsB;AACtB,MAAI,eAAe,qBAAqB;AACtC,WAAO,4BAA4B,SAAS;AAAA,EAC9C;AACA,MAAI,eAAe,6BAA6B;AAC9C,WAAO,mCAAmC,SAAS;AAAA,EACrD;AACA,SAAO;AACT;AAKO,SAAS,6BACd,OACG;AACH,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAO,GAAG,IAAI,uBAAuB,KAAK;AAAA,IAC5C,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kCAEd,QAAkB;AAClB,SAAO,OAAO,IAAI,CAAC,UAAU,6BAA6B,KAAK,CAAC;AAClE;AAEO,SAAS,sBACd,QACiC;AACjC,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,UAAU,QAAQ;AACpB,WAAO,EAAE,MAAM,OAAO,KAAK;AAAA,EAC7B;AAEA,SAAO,EAAE,MAAM,OAAO,GAAG;AAC3B;AAKO,SAAS,mBAAmB,OAAoC;AACrE,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,QAAM,MAAM;AAGZ,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,EAAE,QAAQ,KAAM,QAAO;AAE5C,SAAO;AACT;","names":[]}
@@ -1,4 +1,4 @@
1
- // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/utils.mjs
1
+ // ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.18_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/utils.mjs
2
2
  function formatDuration(ms) {
3
3
  if (ms < 1e3) return `${Math.round(ms)}ms`;
4
4
  return `${(ms / 1e3).toFixed(2)}s`;
@@ -54,7 +54,7 @@ function matchesPattern(path, pattern) {
54
54
  return new RegExp(`^${regexPattern}$`).test(path);
55
55
  }
56
56
 
57
- // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/logger.mjs
57
+ // ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.18_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/logger.mjs
58
58
  function isPlainObject(val) {
59
59
  return val !== null && typeof val === "object" && !Array.isArray(val);
60
60
  }
@@ -362,4 +362,4 @@ export {
362
362
  createRequestLogger,
363
363
  logger
364
364
  };
365
- //# sourceMappingURL=chunk-6FD7OBGM.js.map
365
+ //# sourceMappingURL=chunk-HQANMV7R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/evlog@1.11.0_next@15.5.18_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/src/utils.ts","../../../node_modules/.pnpm/evlog@1.11.0_next@15.5.18_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/src/logger.ts","../src/utils/logger/index.ts"],"sourcesContent":["import type { EnvironmentContext, LogLevel } from './types'\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`\n }\n return `${(ms / 1000).toFixed(2)}s`\n}\n\nexport function isServer(): boolean {\n return typeof window === 'undefined'\n}\n\nexport function isClient(): boolean {\n return typeof window !== 'undefined'\n}\n\nexport function isDev(): boolean {\n if (typeof process !== 'undefined') {\n return process.env.NODE_ENV !== 'production'\n }\n if (typeof window !== 'undefined') {\n return true\n }\n return false\n}\n\nexport function detectEnvironment(): Partial<EnvironmentContext> {\n const env = typeof process !== 'undefined' ? process.env : {}\n const defaultEnvironment = isDev() ? 'development' : 'production'\n\n return {\n environment: env.NODE_ENV || defaultEnvironment,\n service: env.SERVICE_NAME || 'app',\n version: env.APP_VERSION,\n commitHash: env.COMMIT_SHA\n || env.GITHUB_SHA\n || env.VERCEL_GIT_COMMIT_SHA\n || env.CF_PAGES_COMMIT_SHA,\n region: env.VERCEL_REGION\n || env.AWS_REGION\n || env.FLY_REGION\n || env.CF_REGION,\n }\n}\n\nexport function getConsoleMethod(level: LogLevel): LogLevel {\n return level\n}\n\nexport const colors = {\n reset: '\\x1B[0m',\n bold: '\\x1B[1m',\n dim: '\\x1B[2m',\n red: '\\x1B[31m',\n green: '\\x1B[32m',\n yellow: '\\x1B[33m',\n blue: '\\x1B[34m',\n magenta: '\\x1B[35m',\n cyan: '\\x1B[36m',\n white: '\\x1B[37m',\n gray: '\\x1B[90m',\n} as const\n\nexport function getLevelColor(level: string): string {\n switch (level) {\n case 'error':\n return colors.red\n case 'warn':\n return colors.yellow\n case 'info':\n return colors.cyan\n case 'debug':\n return colors.gray\n default:\n return colors.white\n }\n}\n\n/** Headers that should never be passed to hooks for security */\nexport const SENSITIVE_HEADERS = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-auth-token',\n 'proxy-authorization',\n]\n\nexport function filterSafeHeaders(headers: Record<string, string>): Record<string, string> {\n const safeHeaders: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(headers)) {\n if (!SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n safeHeaders[key] = value\n }\n }\n\n return safeHeaders\n}\n\n/**\n * Match a path against a glob pattern.\n * Supports * (any chars except /) and ** (any chars including /).\n */\nexport function matchesPattern(path: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars except * and ?\n .replace(/\\*\\*/g, '{{GLOBSTAR}}') // Temp placeholder for **\n .replace(/\\*/g, '[^/]*') // * matches anything except /\n .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including /\n .replace(/\\?/g, '[^/]') // ? matches single char except /\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(path)\n}\n","import type { DrainContext, EnvironmentContext, FieldContext, Log, LogLevel, LoggerConfig, RequestLogger, RequestLoggerOptions, SamplingConfig, TailSamplingContext, WideEvent } from './types'\nimport { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isDev, matchesPattern } from './utils'\n\nfunction isPlainObject(val: unknown): val is Record<string, unknown> {\n return val !== null && typeof val === 'object' && !Array.isArray(val)\n}\n\nfunction deepDefaults(base: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n const result = { ...base }\n for (const key in defaults) {\n const baseVal = result[key]\n const defaultVal = defaults[key]\n if (baseVal === undefined || baseVal === null) {\n result[key] = defaultVal\n } else if (isPlainObject(baseVal) && isPlainObject(defaultVal)) {\n result[key] = deepDefaults(baseVal, defaultVal)\n }\n }\n return result\n}\n\nlet globalEnv: EnvironmentContext = {\n service: 'app',\n environment: 'development',\n}\n\nlet globalPretty = isDev()\nlet globalSampling: SamplingConfig = {}\nlet globalStringify = true\nlet globalDrain: ((ctx: DrainContext) => void | Promise<void>) | undefined\nlet globalEnabled = true\n\n/**\n * Initialize the logger with configuration.\n * Call this once at application startup.\n */\nexport function initLogger(config: LoggerConfig = {}): void {\n globalEnabled = config.enabled ?? true\n const detected = detectEnvironment()\n\n globalEnv = {\n service: config.env?.service ?? detected.service ?? 'app',\n environment: config.env?.environment ?? detected.environment ?? 'development',\n version: config.env?.version ?? detected.version,\n commitHash: config.env?.commitHash ?? detected.commitHash,\n region: config.env?.region ?? detected.region,\n }\n\n globalPretty = config.pretty ?? isDev()\n globalSampling = config.sampling ?? {}\n globalStringify = config.stringify ?? true\n globalDrain = config.drain\n}\n\n/**\n * Check if logging is globally enabled.\n */\nexport function isEnabled(): boolean {\n return globalEnabled\n}\n\n/**\n * Determine if a log at the given level should be emitted based on sampling config.\n * Error level defaults to 100% (always logged) unless explicitly configured otherwise.\n */\nfunction shouldSample(level: LogLevel): boolean {\n const { rates } = globalSampling\n if (!rates) {\n return true // No sampling configured, log everything\n }\n\n // Error defaults to 100% unless explicitly set\n const percentage = level === 'error' && rates.error === undefined\n ? 100\n : rates[level] ?? 100\n\n // 0% = never log, 100% = always log\n if (percentage <= 0) return false\n if (percentage >= 100) return true\n\n return Math.random() * 100 < percentage\n}\n\n/**\n * Evaluate tail sampling conditions to determine if a log should be force-kept.\n * Returns true if ANY condition matches (OR logic).\n */\nexport function shouldKeep(ctx: TailSamplingContext): boolean {\n const { keep } = globalSampling\n if (!keep?.length) return false\n\n return keep.some((condition) => {\n if (condition.status !== undefined && ctx.status !== undefined && ctx.status >= condition.status) {\n return true\n }\n if (condition.duration !== undefined && ctx.duration !== undefined && ctx.duration >= condition.duration) {\n return true\n }\n if (condition.path && ctx.path && matchesPattern(ctx.path, condition.path)) {\n return true\n }\n return false\n })\n}\n\nfunction emitWideEvent(level: LogLevel, event: Record<string, unknown>, skipSamplingCheck = false): WideEvent | null {\n if (!globalEnabled) return null\n\n if (!skipSamplingCheck && !shouldSample(level)) {\n return null\n }\n\n const formatted: WideEvent = {\n timestamp: new Date().toISOString(),\n level,\n ...globalEnv,\n ...event,\n }\n\n if (globalPretty) {\n prettyPrintWideEvent(formatted)\n } else if (globalStringify) {\n console[getConsoleMethod(level)](JSON.stringify(formatted))\n } else {\n console[getConsoleMethod(level)](formatted)\n }\n\n if (globalDrain) {\n Promise.resolve(globalDrain({ event: formatted })).catch((err) => {\n console.error('[evlog] drain failed:', err)\n })\n }\n\n return formatted\n}\n\nfunction emitTaggedLog(level: LogLevel, tag: string, message: string): void {\n if (!globalEnabled) return\n\n if (globalPretty) {\n if (!shouldSample(level)) {\n return\n }\n const color = getLevelColor(level)\n const timestamp = new Date().toISOString().slice(11, 23)\n console.log(`${colors.dim}${timestamp}${colors.reset} ${color}[${tag}]${colors.reset} ${message}`)\n return\n }\n emitWideEvent(level, { tag, message })\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return String(value)\n }\n if (typeof value === 'object') {\n // Flatten object to key=value pairs\n const pairs: string[] = []\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v !== undefined && v !== null) {\n if (typeof v === 'object') {\n // For nested objects, show as JSON\n pairs.push(`${k}=${JSON.stringify(v)}`)\n } else {\n pairs.push(`${k}=${v}`)\n }\n }\n }\n return pairs.join(' ')\n }\n return String(value)\n}\n\nfunction prettyPrintWideEvent(event: Record<string, unknown>): void {\n const { timestamp, level, service, environment, version, ...rest } = event\n const levelColor = getLevelColor(level as string)\n const ts = (timestamp as string).slice(11, 23)\n\n let header = `${colors.dim}${ts}${colors.reset} ${levelColor}${(level as string).toUpperCase()}${colors.reset}`\n header += ` ${colors.cyan}[${service}]${colors.reset}`\n\n if (rest.method && rest.path) {\n header += ` ${rest.method} ${rest.path}`\n delete rest.method\n delete rest.path\n }\n\n if (rest.status) {\n const statusColor = (rest.status as number) >= 400 ? colors.red : colors.green\n header += ` ${statusColor}${rest.status}${colors.reset}`\n delete rest.status\n }\n\n if (rest.duration) {\n header += ` ${colors.dim}in ${rest.duration}${colors.reset}`\n delete rest.duration\n }\n\n console.log(header)\n\n const entries = Object.entries(rest).filter(([_, v]) => v !== undefined)\n const lastIndex = entries.length - 1\n\n entries.forEach(([key, value], index) => {\n const isLast = index === lastIndex\n const prefix = isLast ? '└─' : '├─'\n const formatted = formatValue(value)\n console.log(` ${colors.dim}${prefix}${colors.reset} ${colors.cyan}${key}:${colors.reset} ${formatted}`)\n })\n}\n\nfunction createLogMethod(level: LogLevel) {\n return function logMethod(tagOrEvent: string | Record<string, unknown>, message?: string): void {\n if (typeof tagOrEvent === 'string' && message !== undefined) {\n emitTaggedLog(level, tagOrEvent, message)\n } else if (typeof tagOrEvent === 'object') {\n emitWideEvent(level, tagOrEvent)\n } else {\n emitTaggedLog(level, 'log', String(tagOrEvent))\n }\n }\n}\n\n/**\n * Simple logging API - as easy as console.log\n *\n * @example\n * ```ts\n * log.info('auth', 'User logged in')\n * log.error({ action: 'payment', error: 'failed' })\n * ```\n */\nconst _log: Log = {\n info: createLogMethod('info'),\n error: createLogMethod('error'),\n warn: createLogMethod('warn'),\n debug: createLogMethod('debug'),\n}\n\nexport { _log as log }\n\nconst noopLogger: RequestLogger = {\n set() {},\n error() {},\n info() {},\n warn() {},\n emit() {\n return null\n },\n getContext() {\n return {}\n },\n}\n\n/**\n * Create a request-scoped logger for building wide events.\n *\n * @example\n * ```ts\n * const log = createRequestLogger({ method: 'POST', path: '/checkout' })\n * log.set({ user: { id: '123' } })\n * log.set({ cart: { items: 3 } })\n * log.emit()\n * ```\n */\nexport function createRequestLogger<T extends object = Record<string, unknown>>(options: RequestLoggerOptions = {}): RequestLogger<T> {\n if (!globalEnabled) return noopLogger as RequestLogger<T>\n\n const startTime = Date.now()\n let context: Record<string, unknown> = {\n method: options.method,\n path: options.path,\n requestId: options.requestId,\n }\n let hasError = false\n let hasWarn = false\n\n function addRequestLog(level: 'info' | 'warn', message: string): void {\n const entry = {\n level,\n message,\n timestamp: new Date().toISOString(),\n }\n\n const requestLogs = Array.isArray(context.requestLogs)\n ? [...context.requestLogs, entry]\n : [entry]\n\n context = {\n ...context,\n requestLogs,\n }\n }\n\n return {\n set(data: FieldContext<T>): void {\n context = deepDefaults(data as Record<string, unknown>, context) as Record<string, unknown>\n },\n\n error(error: Error | string, errorContext?: FieldContext<T>): void {\n hasError = true\n const err = typeof error === 'string' ? new Error(error) : error\n\n const errorData = {\n ...(errorContext as Record<string, unknown>),\n error: {\n name: err.name,\n message: err.message,\n stack: err.stack,\n ...('status' in err && { status: (err as Record<string, unknown>).status }),\n ...('statusText' in err && { statusText: (err as Record<string, unknown>).statusText }),\n ...('statusCode' in err && { statusCode: (err as Record<string, unknown>).statusCode }),\n ...('statusMessage' in err && { statusMessage: (err as Record<string, unknown>).statusMessage }),\n ...('data' in err && { data: (err as Record<string, unknown>).data }),\n ...('cause' in err && { cause: (err as unknown as Record<string, unknown>).cause }),\n },\n }\n context = deepDefaults(errorData, context) as Record<string, unknown>\n },\n\n info(message: string, infoContext?: FieldContext<T>): void {\n addRequestLog('info', message)\n if (infoContext) {\n const { requestLogs: _, ...rest } = infoContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n warn(message: string, warnContext?: FieldContext<T>): void {\n hasWarn = true\n addRequestLog('warn', message)\n if (warnContext) {\n const { requestLogs: _, ...rest } = warnContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n emit(overrides?: FieldContext<T> & { _forceKeep?: boolean }): WideEvent | null {\n const durationMs = Date.now() - startTime\n const duration = formatDuration(durationMs)\n const level: LogLevel = hasError ? 'error' : hasWarn ? 'warn' : 'info'\n\n // Extract _forceKeep from overrides (set by evlog:emit:keep hook)\n const { _forceKeep, ...restOverrides } = (overrides ?? {}) as Record<string, unknown> & { _forceKeep?: boolean }\n\n // Build tail sampling context\n const tailCtx: TailSamplingContext = {\n status: (context.status ?? restOverrides.status) as number | undefined,\n duration: durationMs,\n path: context.path as string | undefined,\n method: context.method as string | undefined,\n context: { ...context, ...restOverrides },\n }\n\n // Tail sampling: force keep if hook or built-in conditions match\n const forceKeep = _forceKeep || shouldKeep(tailCtx)\n\n // Apply head sampling only if not force-kept\n if (!forceKeep && !shouldSample(level)) {\n return null\n }\n\n return emitWideEvent(level, {\n ...context,\n ...restOverrides,\n duration,\n }, true)\n },\n\n getContext(): FieldContext<T> & Record<string, unknown> {\n return { ...context }\n },\n }\n}\n\n/**\n * Get the current environment context.\n */\nexport function getEnvironment(): EnvironmentContext {\n return { ...globalEnv }\n}\n","import { createRequestLogger, initLogger } from 'evlog'\n\n/**\n * Log level for the Stack logger.\n *\n * Configured via the `STASH_STACK_LOG` environment variable.\n *\n * - `'error'` — Only errors (default when `STASH_STACK_LOG` is not set).\n * - `'info'` — Info and errors.\n * - `'debug'` — Debug, info, and errors.\n */\nexport type LogLevel = 'debug' | 'info' | 'error'\n\nconst validLevels: readonly LogLevel[] = ['debug', 'info', 'error'] as const\n\nfunction levelFromEnv(): LogLevel {\n const env = process.env.STASH_STACK_LOG\n if (env && validLevels.includes(env as LogLevel)) return env as LogLevel\n return 'error'\n}\n\nfunction samplingRatesForLevel(level: LogLevel): Record<string, number> {\n // evlog uses sampling rates: 100 = always emit, 0 = never emit\n switch (level) {\n case 'debug':\n return { debug: 100, info: 100, warn: 100, error: 100 }\n case 'info':\n return { debug: 0, info: 100, warn: 100, error: 100 }\n case 'error':\n default:\n return { debug: 0, info: 0, warn: 0, error: 100 }\n }\n}\n\nlet initialized = false\n\n/**\n * Initialize the Stack logger.\n *\n * The log level is read from the `STASH_STACK_LOG` environment variable.\n * When the variable is not set, the default is `'error'` (errors only).\n *\n * @internal\n */\nexport function initStackLogger(): void {\n if (initialized) return\n initialized = true\n\n const level = levelFromEnv()\n const rates = samplingRatesForLevel(level)\n\n initLogger({\n env: { service: '@cipherstash/stack' },\n enabled: true,\n sampling: { rates },\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// Logger for simple one-off logs used across Stack interfaces.\nexport const logger = {\n debug(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({\n level: 'debug',\n source: '@cipherstash/stack',\n message: safeMessage(args),\n })\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"],"mappings":"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","names":[]}