@cipherstash/stack 0.19.0 → 1.0.0-rc.1

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 (101) hide show
  1. package/CHANGELOG.md +596 -0
  2. package/README.md +376 -276
  3. package/dist/adapter-kit.cjs +1002 -0
  4. package/dist/adapter-kit.cjs.map +1 -0
  5. package/dist/adapter-kit.d.cts +120 -0
  6. package/dist/adapter-kit.d.ts +120 -0
  7. package/dist/adapter-kit.js +122 -0
  8. package/dist/adapter-kit.js.map +1 -0
  9. package/dist/base-operation-AOAIvsSB.d.cts +32 -0
  10. package/dist/base-operation-FXEzUXIq.d.ts +32 -0
  11. package/dist/{chunk-4AVL4VZD.js → chunk-3B5ZX3IS.js} +3 -1
  12. package/dist/chunk-3B5ZX3IS.js.map +1 -0
  13. package/dist/{chunk-U66S7VIF.js → chunk-6SGN52W6.js} +166 -107
  14. package/dist/chunk-6SGN52W6.js.map +1 -0
  15. package/dist/chunk-7333ZC6L.js +48 -0
  16. package/dist/chunk-7333ZC6L.js.map +1 -0
  17. package/dist/{chunk-MP3SSDNN.js → chunk-CLM7E4I6.js} +15 -15
  18. package/dist/{chunk-MP3SSDNN.js.map → chunk-CLM7E4I6.js.map} +1 -1
  19. package/dist/{chunk-OFQ555AX.js → chunk-IDKP6ABU.js} +2 -2
  20. package/dist/{chunk-36AA7IBJ.js → chunk-L7ISHSG7.js} +53 -20
  21. package/dist/chunk-L7ISHSG7.js.map +1 -0
  22. package/dist/{chunk-LBMC4D6D.js → chunk-NVKK7UDN.js} +1 -1
  23. package/dist/chunk-NVKK7UDN.js.map +1 -0
  24. package/dist/chunk-X3JRXEIB.js +98 -0
  25. package/dist/chunk-X3JRXEIB.js.map +1 -0
  26. package/dist/client.cjs +29 -12
  27. package/dist/client.cjs.map +1 -1
  28. package/dist/client.d.cts +3 -2
  29. package/dist/client.d.ts +3 -2
  30. package/dist/client.js +2 -2
  31. package/dist/{table-CIH7jZ2h.d.ts → columns-0lbT9stl.d.ts} +157 -138
  32. package/dist/{table-DihEAlxG.d.cts → columns-Bxv7Oo9o.d.cts} +157 -138
  33. package/dist/dynamodb/index.d.cts +3 -2
  34. package/dist/dynamodb/index.d.ts +3 -2
  35. package/dist/encryption/index.cjs +54 -16
  36. package/dist/encryption/index.cjs.map +1 -1
  37. package/dist/encryption/index.d.cts +807 -6
  38. package/dist/encryption/index.d.ts +807 -6
  39. package/dist/encryption/index.js +6 -6
  40. package/dist/encryption/v3.cjs +1078 -973
  41. package/dist/encryption/v3.cjs.map +1 -1
  42. package/dist/encryption/v3.d.cts +15 -12
  43. package/dist/encryption/v3.d.ts +15 -12
  44. package/dist/encryption/v3.js +50 -22
  45. package/dist/encryption/v3.js.map +1 -1
  46. package/dist/eql/v3/index.cjs +130 -79
  47. package/dist/eql/v3/index.cjs.map +1 -1
  48. package/dist/eql/v3/index.d.cts +115 -13
  49. package/dist/eql/v3/index.d.ts +115 -13
  50. package/dist/eql/v3/index.js +16 -6
  51. package/dist/errors/index.cjs.map +1 -1
  52. package/dist/errors/index.d.cts +5 -5
  53. package/dist/errors/index.d.ts +5 -5
  54. package/dist/errors/index.js +1 -1
  55. package/dist/identity/index.cjs.map +1 -1
  56. package/dist/identity/index.js +2 -2
  57. package/dist/index-BquA71_Y.d.ts +24 -0
  58. package/dist/index-fhWTOV0K.d.cts +24 -0
  59. package/dist/index.cjs +79 -27
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.d.cts +5 -17
  62. package/dist/index.d.ts +5 -17
  63. package/dist/index.js +6 -6
  64. package/dist/schema/index.cjs +29 -12
  65. package/dist/schema/index.cjs.map +1 -1
  66. package/dist/schema/index.d.cts +1 -1
  67. package/dist/schema/index.d.ts +1 -1
  68. package/dist/schema/index.js +2 -2
  69. package/dist/{types-public-CpS5KjwX.d.ts → types-public-QMjYNfQO.d.cts} +765 -726
  70. package/dist/{types-public-CpS5KjwX.d.cts → types-public-QMjYNfQO.d.ts} +765 -726
  71. package/dist/types-public.cjs.map +1 -1
  72. package/dist/types-public.d.cts +1 -1
  73. package/dist/types-public.d.ts +1 -1
  74. package/dist/types-public.js +1 -1
  75. package/dist/wasm-inline.d.ts +779 -405
  76. package/dist/wasm-inline.js +606 -299
  77. package/dist/wasm-inline.js.map +1 -1
  78. package/package.json +25 -53
  79. package/dist/chunk-36AA7IBJ.js.map +0 -1
  80. package/dist/chunk-4AVL4VZD.js.map +0 -1
  81. package/dist/chunk-IADZCZEA.js +0 -23
  82. package/dist/chunk-IADZCZEA.js.map +0 -1
  83. package/dist/chunk-IBSK6P33.js +0 -209
  84. package/dist/chunk-IBSK6P33.js.map +0 -1
  85. package/dist/chunk-LBMC4D6D.js.map +0 -1
  86. package/dist/chunk-U66S7VIF.js.map +0 -1
  87. package/dist/client-DSGHBN-g.d.cts +0 -834
  88. package/dist/client-DfCrlHXh.d.ts +0 -834
  89. package/dist/drizzle/index.cjs +0 -5617
  90. package/dist/drizzle/index.cjs.map +0 -1
  91. package/dist/drizzle/index.d.cts +0 -358
  92. package/dist/drizzle/index.d.ts +0 -358
  93. package/dist/drizzle/index.js +0 -1220
  94. package/dist/drizzle/index.js.map +0 -1
  95. package/dist/supabase/index.cjs +0 -5951
  96. package/dist/supabase/index.cjs.map +0 -1
  97. package/dist/supabase/index.d.cts +0 -223
  98. package/dist/supabase/index.d.ts +0 -223
  99. package/dist/supabase/index.js +0 -1217
  100. package/dist/supabase/index.js.map +0 -1
  101. /package/dist/{chunk-OFQ555AX.js.map → chunk-IDKP6ABU.js.map} +0 -0
@@ -1,379 +1,40 @@
1
1
  import { JsPlaintext, EncryptedPayload, newClient, EncryptedQuery as EncryptedQuery$1, EncryptedV3Query, AuthStrategy, Encrypted as Encrypted$1 } from '@cipherstash/protect-ffi';
2
2
  import { z } from 'zod';
3
3
 
4
- /** Brand symbol for nominal typing */
5
- declare const __brand: unique symbol;
6
- /** Creates a branded type that is structurally incompatible with the base type */
7
- type Brand<T, B extends string> = T & {
8
- readonly [__brand]: B;
9
- };
10
- type Client = Awaited<ReturnType<typeof newClient>> | undefined;
11
- /** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */
12
- type EncryptedValue = Brand<Encrypted$1, 'encrypted'>;
13
- /** Structural type representing encrypted data stored in the database. Always
14
- * carries a ciphertext. Covers BOTH wire formats: the EQL v2.3 payloads
15
- * (`k: "ct"` / `k: "sv"`) and the EQL v3 payloads (flat `{v: 3, i, c, …}`
16
- * scalars and `{v: 3, k: "sv", i, sv}` SteVec documents). Which format
17
- * `encrypt` produces is selected by the client's
18
- * {@link ClientConfig.eqlVersion}; `decrypt` accepts both regardless.
19
- * v3 scalars carry no `k` discriminator, so narrow with `'k' in payload`
20
- * before reading it. See also `EncryptedValue` for branded nominal typing,
21
- * and {@link EncryptedQuery} for the search-term shape returned by
22
- * `encryptQuery`. */
23
- type Encrypted = EncryptedPayload;
24
- /** Structural type representing an encrypted query term (search needle)
25
- * returned by `encryptQuery` / `encryptQueryBulk` for scalar
26
- * (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path
27
- * queries, plus — under `eqlVersion: 3` — the `eql_v3.jsonb_query`
28
- * containment needle. Carries no ciphertext — matched against stored
29
- * values, never decrypted. v2 JSON containment queries (`ste_vec_term`)
30
- * return a storage-shaped {@link Encrypted} payload instead. */
31
- type EncryptedQuery = EncryptedQuery$1 | EncryptedV3Query;
32
4
  /**
33
- * Plaintext values the SDK accepts for encryption.
5
+ * Allowed cast types for CipherStash schema fields.
34
6
  *
35
- * Widens the FFI's `JsPlaintext` (`string | number | boolean |
36
- * Record<string, unknown> | JsPlaintext[]`) with `Date`. `Date` is a supported
37
- * cast target that is omitted from the FFI's `JsPlaintext` INPUT union, but it
38
- * serializes at the boundary via `toJSON` (ISO string), so it is accepted on the
39
- * way in.
7
+ * **Possible values:**
8
+ * - `"bigint"`
9
+ * - `"boolean"`
10
+ * - `"date"`
11
+ * - `"timestamp"`
12
+ * - `"number"`
13
+ * - `"string"`
14
+ * - `"json"`
15
+ * - `"text"`
40
16
  *
41
- * `bigint` is intentionally NOT included: the native `@cipherstash/protect-ffi`
42
- * build cannot marshal a JS `bigint` (V8 throws "Do not know how to serialize a
43
- * BigInt") and rejects a `string` for a `big_int` column. The v3 int8 domains
44
- * are therefore omitted from the SDK entirely (see `eql/v3`) until the FFI
45
- * supports lossless bigint I/O; `bigint` returns here alongside them.
17
+ * @remarks
18
+ * This is a Zod enum used at runtime to validate schema definitions.
19
+ * Use {@link CastAs} when typing your own code.
46
20
  *
47
- * When the upstream FFI `JsPlaintext` is corrected to include `Date`, the `Date`
48
- * arm can collapse back into `JsPlaintext`.
21
+ * @internal
49
22
  */
50
- type Plaintext = JsPlaintext | Date;
51
- type KeysetIdentifier = {
52
- name: string;
53
- } | {
54
- id: string;
55
- };
56
- type ClientConfig = {
57
- /**
58
- * The CipherStash workspace CRN (Cloud Resource Name).
59
- * Format: `crn:<region>.aws:<workspace-id>`.
60
- * Can also be set via the `CS_WORKSPACE_CRN` environment variable.
61
- */
62
- workspaceCrn?: string;
63
- /**
64
- * The API access key used for authenticating with the CipherStash API.
65
- * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.
66
- * Obtain this from the CipherStash dashboard after creating a workspace.
67
- */
68
- accessKey?: string;
69
- /**
70
- * The client identifier used to authenticate with CipherStash services.
71
- * Can also be set via the `CS_CLIENT_ID` environment variable.
72
- * Generated during workspace onboarding in the CipherStash dashboard.
73
- */
74
- clientId?: string;
75
- /**
76
- * The client key material used in combination with ZeroKMS for encryption operations.
77
- * Can also be set via the `CS_CLIENT_KEY` environment variable.
78
- * Generated during workspace onboarding in the CipherStash dashboard.
79
- */
80
- clientKey?: string;
81
- /**
82
- * An optional keyset identifier for multi-tenant encryption.
83
- * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.
84
- * Specify by name (`{ name: "tenant-a" }`) or UUID (`{ id: "..." }`).
85
- * Keysets are created and managed in the
86
- * [dashboard](https://dashboard.cipherstash.com/workspaces/_/keysets); omit to
87
- * use the workspace's default keyset. A client is bound to one keyset for its
88
- * lifetime, so use one client per tenant.
89
- *
90
- * @see {@link Encryption} for the full keysets walkthrough.
91
- */
92
- keyset?: KeysetIdentifier;
93
- /**
94
- * An optional authentication strategy for ZeroKMS requests, from
95
- * `@cipherstash/auth` (re-exported by `@cipherstash/stack`). When provided,
96
- * its `getToken()` is invoked on every ZeroKMS request and takes precedence
97
- * over the default `auto` strategy (the `clientKey` is still required for
98
- * encryption). Use:
99
- *
100
- * - `OidcFederationStrategy` for per-user, identity-bound encryption —
101
- * federates an end user's OIDC JWT into a CTS service token, so requests
102
- * authenticate as that user. Pair with `.withLockContext({ identityClaim })`
103
- * to bind the data key to a claim. This replaces the older
104
- * `LockContext.identify()` ceremony.
105
- * - `AccessKeyStrategy` for service-to-service / CI, or any custom
106
- * `{ getToken() }` object for bespoke token acquisition / caching.
107
- *
108
- * Leave unset to use the default `auto` strategy, which reads credentials
109
- * from the `CS_*` environment variables and falls back to the local dev
110
- * profile created by `npx stash auth login`.
111
- *
112
- * @see {@link AuthStrategy}
113
- * @see {@link Encryption} for a full walkthrough of the authentication options.
114
- */
115
- authStrategy?: AuthStrategy;
116
- /**
117
- * @deprecated Renamed to {@link ClientConfig.authStrategy}. Still honoured for
118
- * backwards compatibility — passing it logs a deprecation warning at runtime —
119
- * but it will be removed in a future release. Set `authStrategy` instead.
120
- */
121
- strategy?: AuthStrategy;
122
- /**
123
- * The EQL wire version the client emits — one FFI client always emits
124
- * exactly one wire format.
125
- *
126
- * - `2` (the protect-ffi default): payloads target the
127
- * `eql_v2_encrypted` column type.
128
- * - `3`: payloads target the per-capability `eql_v3` domains
129
- * (`eql_v3.text_eq`, `eql_v3.integer_ord_ore`, `eql_v3.json`, …),
130
- * derived from each column's `cast_as` and indexes.
131
- *
132
- * When omitted, {@link Encryption} auto-detects from the schema set:
133
- * EQL v3 tables (from `@cipherstash/stack/v3`, marked by
134
- * `buildColumnKeyMap()`) select `3`; v2 tables leave the FFI default
135
- * (`2`) untouched. Mixing v2 and v3 tables in one client is an error —
136
- * split them across two clients instead.
137
- *
138
- * `decrypt` accepts BOTH formats regardless of this setting, so v2 and
139
- * v3 data can coexist during a migration.
140
- *
141
- * v3 limitation (protect-ffi 0.27): `encryptQuery` supports only JSON
142
- * containment queries — scalar-index and selector queries throw
143
- * `EQL_V3_QUERY_UNSUPPORTED` until a v3 scalar query wire shape exists.
144
- */
145
- eqlVersion?: 2 | 3;
146
- };
147
- type AtLeastOneCsTable<T> = [T, ...T[]];
148
- /** Structural contract for a column builder the client can consume for STORAGE
149
- * (`encrypt`). Satisfied by v2 `EncryptedColumn` / `EncryptedField` AND v3
150
- * `EncryptedTextSearchColumn` — fields ARE encryptable, so this stays wide. */
151
- interface BuildableColumn {
152
- getName(): string;
153
- build(): ColumnSchema;
154
- }
155
- /** Structural contract for a column the client can consume for QUERIES
156
- * (`encryptQuery` / search terms). Narrower than `BuildableColumn`: it must
157
- * EXCLUDE non-queryable `EncryptedField` (a field has no indexes). A v2
158
- * `EncryptedColumn` qualifies via the nominal arm; a v3 queryable concrete
159
- * type qualifies via the `getEqlType()` structural arm; `EncryptedField` (no
160
- * `getEqlType`, not an `EncryptedColumn`) is rejected. */
161
- interface BuildableV3QueryableColumn extends BuildableColumn {
162
- getEqlType(): string;
163
- getQueryCapabilities(): {
164
- equality: boolean;
165
- orderAndRange: boolean;
166
- freeTextSearch: boolean;
167
- };
168
- isQueryable(): true;
169
- }
170
- type BuildableQueryColumn = EncryptedColumn | BuildableV3QueryableColumn;
171
- /** Structural contract for a table builder the client can consume. Satisfied by
172
- * v2 and v3 `EncryptedTable` alike. */
173
- interface BuildableTable {
174
- tableName: string;
175
- build(): {
176
- tableName: string;
177
- columns: Record<string, ColumnSchema>;
178
- };
179
- /**
180
- * Optional map from a model field's JS property name to its encrypt-config
181
- * column name (the DB name). Present when the two can differ — v3 tables key
182
- * their config by DB name (`column.getName()`) while models are written with
183
- * JS property keys, so the model path must match by property but address the
184
- * FFI/config by DB name.
185
- *
186
- * Absent on v2 tables, whose `build()` already keys columns by the JS property
187
- * name; the model path then matches and addresses by that same key.
188
- */
189
- buildColumnKeyMap?(): Record<string, string>;
190
- }
191
- type EncryptionClientConfig = {
192
- schemas: AtLeastOneCsTable<BuildableTable>;
193
- config?: ClientConfig;
194
- };
195
23
  /**
196
- * The literal column map of a buildable table, read from its type-level
197
- * `_columnType` brand. Both v2 and v3 `EncryptedTable` carry this brand, so this
198
- * recovers the literal column keys structurally.
199
- *
200
- * This deliberately uses the `_columnType` brand rather than `build().columns`:
201
- * `BuildableTable.build()` is typed to return `Record<string, ColumnSchema>`,
202
- * which erases the literal keys and would mark EVERY model field as encrypted.
203
- *
204
- * The fallbacks resolve to `Record<never, never>` (a no-key type), NOT `never`:
205
- * a value typed as the bare structural `BuildableTable` carries no `_columnType`
206
- * brand, and `keyof never` is `string | number | symbol` — which would wrongly
207
- * mark EVERY model field as encrypted. `keyof Record<never, never>` is `never`,
208
- * so `EncryptedFromBuildableTable` degrades gracefully to the model unchanged.
24
+ * EQL cast types the PostgreSQL-aligned types that EQL actually accepts.
25
+ * These are stored in the `cast_as` field of the EncryptConfig.
209
26
  */
210
- type BuildableTableColumns<T extends BuildableTable> = T extends {
211
- readonly _columnType: infer C;
212
- } ? C extends Record<string, unknown> ? C : Record<never, never> : Record<never, never>;
27
+ declare const eqlCastAsEnum: z.ZodDefault<z.ZodEnum<["text", "int", "small_int", "big_int", "real", "double", "boolean", "date", "timestamp", "jsonb"]>>;
213
28
  /**
214
- * Maps a plaintext model type to its encrypted form using a buildable table.
29
+ * SDK-facing data types developer-friendly aliases accepted by `dataType()`.
215
30
  *
216
- * Fields whose keys match a column defined in `Table` (via its `_columnType`
217
- * brand) become `Encrypted` (`Encrypted | null` when the source field is
218
- * nullable); all other fields retain their original types from `T`. Works for
219
- * both v2 and v3 tables. See {@link EncryptedFromSchema} for the v2-specific
220
- * variant retained for backward compatibility.
221
- */
222
- type EncryptedFromBuildableTable<T, Table extends BuildableTable> = {
223
- [K in keyof T]: [K] extends [keyof BuildableTableColumns<Table>] ? null extends T[K] ? Encrypted | null : Encrypted : T[K];
224
- };
225
- /**
226
- * Options for single-value encrypt operations.
227
- * Use a column from your table schema (from {@link encryptedColumn}) or a nested
228
- * field (from {@link encryptedField}) as the target for encryption.
31
+ * `timestamp` is distinct from `date`: `date` is calendar-date only (time-of-day
32
+ * truncated to midnight), while `timestamp` preserves the full date+time. v3
33
+ * `timestamp` domains set `cast_as: 'timestamp'` so the FFI keeps the instant.
229
34
  */
230
- type EncryptOptions = {
231
- /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */
232
- column: BuildableColumn;
233
- table: BuildableTable;
234
- };
235
- /** Format for encrypted query/search term return values */
236
- type EncryptedReturnType = 'eql' | 'composite-literal' | 'escaped-composite-literal';
237
- type SearchTerm = {
238
- value: Plaintext;
239
- column: BuildableQueryColumn;
240
- table: BuildableTable;
241
- returnType?: EncryptedReturnType;
242
- };
243
- /** Encrypted search term result. `eql` return type yields either a storage
244
- * payload (`Encrypted`, for `ste_vec_term`) or a query-only term
245
- * (`EncryptedQuery`, for scalar lookups and `ste_vec_selector`); the
246
- * `composite-literal` return types yield a string. */
247
- type EncryptedSearchTerm = Encrypted | EncryptedQuery | string;
248
- /** Result of encryptQuery (single or batch). `eql` return type yields either a
249
- * storage payload (`Encrypted`) or a query-only term (`EncryptedQuery`); the
250
- * `composite-literal` return types yield a string. */
251
- type EncryptedQueryResult = Encrypted | EncryptedQuery | string | null;
252
- type EncryptedFields<T> = {
253
- [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K];
254
- };
255
- type OtherFields<T> = {
256
- [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K];
257
- };
258
- type DecryptedFields<T> = {
259
- [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: null extends T[K] ? string | null : string;
260
- };
261
- /** Model with encrypted fields replaced by plaintext (decrypted) values */
262
- type Decrypted<T> = OtherFields<T> & DecryptedFields<T>;
35
+ declare const castAsEnum: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "timestamp", "number", "string", "json", "text"]>>;
263
36
  /**
264
- * Maps a plaintext model type to its encrypted form using the table schema.
265
- *
266
- * Fields whose keys match columns defined in `S` become `Encrypted`;
267
- * all other fields retain their original types from `T`.
268
- *
269
- * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an
270
- * explicit `<User>` type argument without specifying `S`), the type degrades
271
- * gracefully to `T` — preserving backward compatibility.
272
- *
273
- * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)
274
- * @typeParam S - The table schema column definition, inferred from the `table` argument
275
- *
276
- * @example
277
- * ```typescript
278
- * type User = { id: string; email: string }
279
- * // With a schema that defines `email`:
280
- * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>
281
- * // => { id: string; email: Encrypted }
282
- * ```
283
- */
284
- type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {
285
- [K in keyof T]: [K] extends [keyof S] ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField] ? null extends T[K] ? Encrypted | null : Encrypted : T[K] : T[K];
286
- };
287
- type BulkEncryptPayload = Array<{
288
- id?: string;
289
- plaintext: Plaintext | null;
290
- }>;
291
- type BulkEncryptedData = Array<{
292
- id?: string;
293
- data: Encrypted | null;
294
- }>;
295
- type BulkDecryptPayload = Array<{
296
- id?: string;
297
- data: Encrypted | null;
298
- }>;
299
- type BulkDecryptedData = Array<DecryptionResult<JsPlaintext | null>>;
300
- type DecryptionSuccess<T> = {
301
- error?: never;
302
- data: T;
303
- id?: string;
304
- };
305
- type DecryptionError<T> = {
306
- error: T;
307
- id?: string;
308
- data?: never;
309
- };
310
- /**
311
- * Result type for individual items in bulk decrypt operations.
312
- * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations
313
- * can have per-item failures.
314
- */
315
- type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>;
316
- /**
317
- * User-facing query type names for encrypting query values.
318
- *
319
- * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
320
- * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
321
- * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
322
- * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)
323
- * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)
324
- * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)
325
- */
326
- type QueryTypeName = 'orderAndRange' | 'freeTextSearch' | 'equality' | 'steVecSelector' | 'steVecTerm' | 'searchableJson';
327
- declare const queryTypes: {
328
- readonly orderAndRange: "orderAndRange";
329
- readonly freeTextSearch: "freeTextSearch";
330
- readonly equality: "equality";
331
- readonly steVecSelector: "steVecSelector";
332
- readonly steVecTerm: "steVecTerm";
333
- readonly searchableJson: "searchableJson";
334
- };
335
- /** @internal */
336
- type QueryTermBase = {
337
- column: BuildableQueryColumn;
338
- table: BuildableTable;
339
- queryType?: QueryTypeName;
340
- returnType?: EncryptedReturnType;
341
- };
342
- type EncryptQueryOptions = QueryTermBase;
343
- type ScalarQueryTerm = QueryTermBase & {
344
- value: Plaintext;
345
- };
346
-
347
- /**
348
- * Allowed cast types for CipherStash schema fields.
349
- *
350
- * **Possible values:**
351
- * - `"bigint"`
352
- * - `"boolean"`
353
- * - `"date"`
354
- * - `"timestamp"`
355
- * - `"number"`
356
- * - `"string"`
357
- * - `"json"`
358
- * - `"text"`
359
- *
360
- * @remarks
361
- * This is a Zod enum used at runtime to validate schema definitions.
362
- * Use {@link CastAs} when typing your own code.
363
- *
364
- * @internal
365
- */
366
- /**
367
- * EQL cast types — the PostgreSQL-aligned types that EQL actually accepts.
368
- * These are stored in the `cast_as` field of the EncryptConfig.
369
- */
370
- declare const eqlCastAsEnum: z.ZodDefault<z.ZodEnum<["text", "int", "small_int", "big_int", "real", "double", "boolean", "date", "timestamp", "jsonb"]>>;
371
- /**
372
- * SDK-facing data types — developer-friendly aliases accepted by `dataType()`.
373
- */
374
- declare const castAsEnum: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "timestamp", "number", "string", "json", "text"]>>;
375
- /**
376
- * Map SDK-facing data types to EQL `cast_as` values.
37
+ * Map SDK-facing data types to EQL `cast_as` values.
377
38
  *
378
39
  * The SDK accepts developer-friendly types like `'string'` and `'number'`,
379
40
  * but EQL expects PostgreSQL-aligned types like `'text'` and `'double'`.
@@ -387,6 +48,7 @@ declare const tokenFilterSchema: z.ZodObject<{
387
48
  kind: "downcase";
388
49
  }>;
389
50
  declare const oreIndexOptsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
51
+ declare const opeIndexOptsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
390
52
  declare const uniqueIndexOptsSchema: z.ZodObject<{
391
53
  token_filters: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
392
54
  kind: z.ZodLiteral<"downcase">;
@@ -432,28 +94,28 @@ declare const matchIndexOptsSchema: z.ZodObject<{
432
94
  m: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
433
95
  include_original: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
434
96
  }, "strip", z.ZodTypeAny, {
435
- token_filters?: {
436
- kind: "downcase";
437
- }[] | undefined;
438
97
  tokenizer?: {
439
98
  kind: "standard";
440
99
  } | {
441
100
  kind: "ngram";
442
101
  token_length: number;
443
102
  } | undefined;
103
+ token_filters?: {
104
+ kind: "downcase";
105
+ }[] | undefined;
444
106
  k?: number | undefined;
445
107
  m?: number | undefined;
446
108
  include_original?: boolean | undefined;
447
109
  }, {
448
- token_filters?: {
449
- kind: "downcase";
450
- }[] | undefined;
451
110
  tokenizer?: {
452
111
  kind: "standard";
453
112
  } | {
454
113
  kind: "ngram";
455
114
  token_length: number;
456
115
  } | undefined;
116
+ token_filters?: {
117
+ kind: "downcase";
118
+ }[] | undefined;
457
119
  k?: number | undefined;
458
120
  m?: number | undefined;
459
121
  include_original?: boolean | undefined;
@@ -473,6 +135,7 @@ declare const steVecIndexOptsSchema: z.ZodObject<{
473
135
  wildcard?: boolean | undefined;
474
136
  position?: boolean | undefined;
475
137
  }>]>>;
138
+ mode: z.ZodOptional<z.ZodEnum<["compat", "standard"]>>;
476
139
  }, "strip", z.ZodTypeAny, {
477
140
  prefix: string;
478
141
  array_index_mode?: "all" | "none" | {
@@ -480,6 +143,7 @@ declare const steVecIndexOptsSchema: z.ZodObject<{
480
143
  wildcard?: boolean | undefined;
481
144
  position?: boolean | undefined;
482
145
  } | undefined;
146
+ mode?: "standard" | "compat" | undefined;
483
147
  }, {
484
148
  prefix: string;
485
149
  array_index_mode?: "all" | "none" | {
@@ -487,11 +151,13 @@ declare const steVecIndexOptsSchema: z.ZodObject<{
487
151
  wildcard?: boolean | undefined;
488
152
  position?: boolean | undefined;
489
153
  } | undefined;
154
+ mode?: "standard" | "compat" | undefined;
490
155
  }>;
491
156
  declare const columnSchema: z.ZodDefault<z.ZodObject<{
492
157
  cast_as: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "timestamp", "number", "string", "json", "text"]>>;
493
158
  indexes: z.ZodDefault<z.ZodObject<{
494
159
  ore: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
160
+ ope: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
495
161
  unique: z.ZodOptional<z.ZodObject<{
496
162
  token_filters: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
497
163
  kind: z.ZodLiteral<"downcase">;
@@ -537,28 +203,28 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
537
203
  m: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
538
204
  include_original: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
539
205
  }, "strip", z.ZodTypeAny, {
540
- token_filters?: {
541
- kind: "downcase";
542
- }[] | undefined;
543
206
  tokenizer?: {
544
207
  kind: "standard";
545
208
  } | {
546
209
  kind: "ngram";
547
210
  token_length: number;
548
211
  } | undefined;
212
+ token_filters?: {
213
+ kind: "downcase";
214
+ }[] | undefined;
549
215
  k?: number | undefined;
550
216
  m?: number | undefined;
551
217
  include_original?: boolean | undefined;
552
218
  }, {
553
- token_filters?: {
554
- kind: "downcase";
555
- }[] | undefined;
556
219
  tokenizer?: {
557
220
  kind: "standard";
558
221
  } | {
559
222
  kind: "ngram";
560
223
  token_length: number;
561
224
  } | undefined;
225
+ token_filters?: {
226
+ kind: "downcase";
227
+ }[] | undefined;
562
228
  k?: number | undefined;
563
229
  m?: number | undefined;
564
230
  include_original?: boolean | undefined;
@@ -578,6 +244,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
578
244
  wildcard?: boolean | undefined;
579
245
  position?: boolean | undefined;
580
246
  }>]>>;
247
+ mode: z.ZodOptional<z.ZodEnum<["compat", "standard"]>>;
581
248
  }, "strip", z.ZodTypeAny, {
582
249
  prefix: string;
583
250
  array_index_mode?: "all" | "none" | {
@@ -585,6 +252,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
585
252
  wildcard?: boolean | undefined;
586
253
  position?: boolean | undefined;
587
254
  } | undefined;
255
+ mode?: "standard" | "compat" | undefined;
588
256
  }, {
589
257
  prefix: string;
590
258
  array_index_mode?: "all" | "none" | {
@@ -592,27 +260,29 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
592
260
  wildcard?: boolean | undefined;
593
261
  position?: boolean | undefined;
594
262
  } | undefined;
263
+ mode?: "standard" | "compat" | undefined;
595
264
  }>>;
596
265
  }, "strip", z.ZodTypeAny, {
597
- match?: {
266
+ ore?: {} | undefined;
267
+ ope?: {} | undefined;
268
+ unique?: {
598
269
  token_filters?: {
599
270
  kind: "downcase";
600
271
  }[] | undefined;
272
+ } | undefined;
273
+ match?: {
601
274
  tokenizer?: {
602
275
  kind: "standard";
603
276
  } | {
604
277
  kind: "ngram";
605
278
  token_length: number;
606
279
  } | undefined;
607
- k?: number | undefined;
608
- m?: number | undefined;
609
- include_original?: boolean | undefined;
610
- } | undefined;
611
- ore?: {} | undefined;
612
- unique?: {
613
280
  token_filters?: {
614
281
  kind: "downcase";
615
282
  }[] | undefined;
283
+ k?: number | undefined;
284
+ m?: number | undefined;
285
+ include_original?: boolean | undefined;
616
286
  } | undefined;
617
287
  ste_vec?: {
618
288
  prefix: string;
@@ -621,27 +291,29 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
621
291
  wildcard?: boolean | undefined;
622
292
  position?: boolean | undefined;
623
293
  } | undefined;
294
+ mode?: "standard" | "compat" | undefined;
624
295
  } | undefined;
625
296
  }, {
626
- match?: {
297
+ ore?: {} | undefined;
298
+ ope?: {} | undefined;
299
+ unique?: {
627
300
  token_filters?: {
628
301
  kind: "downcase";
629
302
  }[] | undefined;
303
+ } | undefined;
304
+ match?: {
630
305
  tokenizer?: {
631
306
  kind: "standard";
632
307
  } | {
633
308
  kind: "ngram";
634
309
  token_length: number;
635
310
  } | undefined;
636
- k?: number | undefined;
637
- m?: number | undefined;
638
- include_original?: boolean | undefined;
639
- } | undefined;
640
- ore?: {} | undefined;
641
- unique?: {
642
311
  token_filters?: {
643
312
  kind: "downcase";
644
313
  }[] | undefined;
314
+ k?: number | undefined;
315
+ m?: number | undefined;
316
+ include_original?: boolean | undefined;
645
317
  } | undefined;
646
318
  ste_vec?: {
647
319
  prefix: string;
@@ -650,30 +322,32 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
650
322
  wildcard?: boolean | undefined;
651
323
  position?: boolean | undefined;
652
324
  } | undefined;
325
+ mode?: "standard" | "compat" | undefined;
653
326
  } | undefined;
654
327
  }>>;
655
328
  }, "strip", z.ZodTypeAny, {
656
- cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text";
329
+ cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
657
330
  indexes: {
658
- match?: {
331
+ ore?: {} | undefined;
332
+ ope?: {} | undefined;
333
+ unique?: {
659
334
  token_filters?: {
660
335
  kind: "downcase";
661
336
  }[] | undefined;
337
+ } | undefined;
338
+ match?: {
662
339
  tokenizer?: {
663
340
  kind: "standard";
664
341
  } | {
665
342
  kind: "ngram";
666
343
  token_length: number;
667
344
  } | undefined;
668
- k?: number | undefined;
669
- m?: number | undefined;
670
- include_original?: boolean | undefined;
671
- } | undefined;
672
- ore?: {} | undefined;
673
- unique?: {
674
345
  token_filters?: {
675
346
  kind: "downcase";
676
347
  }[] | undefined;
348
+ k?: number | undefined;
349
+ m?: number | undefined;
350
+ include_original?: boolean | undefined;
677
351
  } | undefined;
678
352
  ste_vec?: {
679
353
  prefix: string;
@@ -682,30 +356,32 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
682
356
  wildcard?: boolean | undefined;
683
357
  position?: boolean | undefined;
684
358
  } | undefined;
359
+ mode?: "standard" | "compat" | undefined;
685
360
  } | undefined;
686
361
  };
687
362
  }, {
688
- cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text" | undefined;
363
+ cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
689
364
  indexes?: {
690
- match?: {
365
+ ore?: {} | undefined;
366
+ ope?: {} | undefined;
367
+ unique?: {
691
368
  token_filters?: {
692
369
  kind: "downcase";
693
370
  }[] | undefined;
371
+ } | undefined;
372
+ match?: {
694
373
  tokenizer?: {
695
374
  kind: "standard";
696
375
  } | {
697
376
  kind: "ngram";
698
377
  token_length: number;
699
378
  } | undefined;
700
- k?: number | undefined;
701
- m?: number | undefined;
702
- include_original?: boolean | undefined;
703
- } | undefined;
704
- ore?: {} | undefined;
705
- unique?: {
706
379
  token_filters?: {
707
380
  kind: "downcase";
708
381
  }[] | undefined;
382
+ k?: number | undefined;
383
+ m?: number | undefined;
384
+ include_original?: boolean | undefined;
709
385
  } | undefined;
710
386
  ste_vec?: {
711
387
  prefix: string;
@@ -714,6 +390,7 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
714
390
  wildcard?: boolean | undefined;
715
391
  position?: boolean | undefined;
716
392
  } | undefined;
393
+ mode?: "standard" | "compat" | undefined;
717
394
  } | undefined;
718
395
  } | undefined;
719
396
  }>>;
@@ -724,6 +401,7 @@ declare const encryptConfigSchema: z.ZodObject<{
724
401
  cast_as: z.ZodDefault<z.ZodEnum<["bigint", "boolean", "date", "timestamp", "number", "string", "json", "text"]>>;
725
402
  indexes: z.ZodDefault<z.ZodObject<{
726
403
  ore: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
404
+ ope: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
727
405
  unique: z.ZodOptional<z.ZodObject<{
728
406
  token_filters: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
729
407
  kind: z.ZodLiteral<"downcase">;
@@ -769,28 +447,28 @@ declare const encryptConfigSchema: z.ZodObject<{
769
447
  m: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
770
448
  include_original: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
771
449
  }, "strip", z.ZodTypeAny, {
772
- token_filters?: {
773
- kind: "downcase";
774
- }[] | undefined;
775
450
  tokenizer?: {
776
451
  kind: "standard";
777
452
  } | {
778
453
  kind: "ngram";
779
454
  token_length: number;
780
455
  } | undefined;
456
+ token_filters?: {
457
+ kind: "downcase";
458
+ }[] | undefined;
781
459
  k?: number | undefined;
782
460
  m?: number | undefined;
783
461
  include_original?: boolean | undefined;
784
462
  }, {
785
- token_filters?: {
786
- kind: "downcase";
787
- }[] | undefined;
788
463
  tokenizer?: {
789
464
  kind: "standard";
790
465
  } | {
791
466
  kind: "ngram";
792
467
  token_length: number;
793
468
  } | undefined;
469
+ token_filters?: {
470
+ kind: "downcase";
471
+ }[] | undefined;
794
472
  k?: number | undefined;
795
473
  m?: number | undefined;
796
474
  include_original?: boolean | undefined;
@@ -810,6 +488,7 @@ declare const encryptConfigSchema: z.ZodObject<{
810
488
  wildcard?: boolean | undefined;
811
489
  position?: boolean | undefined;
812
490
  }>]>>;
491
+ mode: z.ZodOptional<z.ZodEnum<["compat", "standard"]>>;
813
492
  }, "strip", z.ZodTypeAny, {
814
493
  prefix: string;
815
494
  array_index_mode?: "all" | "none" | {
@@ -817,6 +496,7 @@ declare const encryptConfigSchema: z.ZodObject<{
817
496
  wildcard?: boolean | undefined;
818
497
  position?: boolean | undefined;
819
498
  } | undefined;
499
+ mode?: "standard" | "compat" | undefined;
820
500
  }, {
821
501
  prefix: string;
822
502
  array_index_mode?: "all" | "none" | {
@@ -824,27 +504,29 @@ declare const encryptConfigSchema: z.ZodObject<{
824
504
  wildcard?: boolean | undefined;
825
505
  position?: boolean | undefined;
826
506
  } | undefined;
507
+ mode?: "standard" | "compat" | undefined;
827
508
  }>>;
828
509
  }, "strip", z.ZodTypeAny, {
829
- match?: {
510
+ ore?: {} | undefined;
511
+ ope?: {} | undefined;
512
+ unique?: {
830
513
  token_filters?: {
831
514
  kind: "downcase";
832
515
  }[] | undefined;
516
+ } | undefined;
517
+ match?: {
833
518
  tokenizer?: {
834
519
  kind: "standard";
835
520
  } | {
836
521
  kind: "ngram";
837
522
  token_length: number;
838
523
  } | undefined;
839
- k?: number | undefined;
840
- m?: number | undefined;
841
- include_original?: boolean | undefined;
842
- } | undefined;
843
- ore?: {} | undefined;
844
- unique?: {
845
524
  token_filters?: {
846
525
  kind: "downcase";
847
526
  }[] | undefined;
527
+ k?: number | undefined;
528
+ m?: number | undefined;
529
+ include_original?: boolean | undefined;
848
530
  } | undefined;
849
531
  ste_vec?: {
850
532
  prefix: string;
@@ -853,27 +535,29 @@ declare const encryptConfigSchema: z.ZodObject<{
853
535
  wildcard?: boolean | undefined;
854
536
  position?: boolean | undefined;
855
537
  } | undefined;
538
+ mode?: "standard" | "compat" | undefined;
856
539
  } | undefined;
857
540
  }, {
858
- match?: {
541
+ ore?: {} | undefined;
542
+ ope?: {} | undefined;
543
+ unique?: {
859
544
  token_filters?: {
860
545
  kind: "downcase";
861
546
  }[] | undefined;
547
+ } | undefined;
548
+ match?: {
862
549
  tokenizer?: {
863
550
  kind: "standard";
864
551
  } | {
865
552
  kind: "ngram";
866
553
  token_length: number;
867
554
  } | undefined;
868
- k?: number | undefined;
869
- m?: number | undefined;
870
- include_original?: boolean | undefined;
871
- } | undefined;
872
- ore?: {} | undefined;
873
- unique?: {
874
555
  token_filters?: {
875
556
  kind: "downcase";
876
557
  }[] | undefined;
558
+ k?: number | undefined;
559
+ m?: number | undefined;
560
+ include_original?: boolean | undefined;
877
561
  } | undefined;
878
562
  ste_vec?: {
879
563
  prefix: string;
@@ -882,30 +566,32 @@ declare const encryptConfigSchema: z.ZodObject<{
882
566
  wildcard?: boolean | undefined;
883
567
  position?: boolean | undefined;
884
568
  } | undefined;
569
+ mode?: "standard" | "compat" | undefined;
885
570
  } | undefined;
886
571
  }>>;
887
572
  }, "strip", z.ZodTypeAny, {
888
- cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text";
573
+ cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
889
574
  indexes: {
890
- match?: {
575
+ ore?: {} | undefined;
576
+ ope?: {} | undefined;
577
+ unique?: {
891
578
  token_filters?: {
892
579
  kind: "downcase";
893
580
  }[] | undefined;
581
+ } | undefined;
582
+ match?: {
894
583
  tokenizer?: {
895
584
  kind: "standard";
896
585
  } | {
897
586
  kind: "ngram";
898
587
  token_length: number;
899
588
  } | undefined;
900
- k?: number | undefined;
901
- m?: number | undefined;
902
- include_original?: boolean | undefined;
903
- } | undefined;
904
- ore?: {} | undefined;
905
- unique?: {
906
589
  token_filters?: {
907
590
  kind: "downcase";
908
591
  }[] | undefined;
592
+ k?: number | undefined;
593
+ m?: number | undefined;
594
+ include_original?: boolean | undefined;
909
595
  } | undefined;
910
596
  ste_vec?: {
911
597
  prefix: string;
@@ -914,31 +600,33 @@ declare const encryptConfigSchema: z.ZodObject<{
914
600
  wildcard?: boolean | undefined;
915
601
  position?: boolean | undefined;
916
602
  } | undefined;
603
+ mode?: "standard" | "compat" | undefined;
917
604
  } | undefined;
918
605
  };
919
606
  }, {
920
- cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text" | undefined;
607
+ cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
921
608
  indexes?: {
922
- match?: {
609
+ ore?: {} | undefined;
610
+ ope?: {} | undefined;
611
+ unique?: {
923
612
  token_filters?: {
924
613
  kind: "downcase";
925
614
  }[] | undefined;
615
+ } | undefined;
616
+ match?: {
926
617
  tokenizer?: {
927
618
  kind: "standard";
928
619
  } | {
929
620
  kind: "ngram";
930
621
  token_length: number;
931
622
  } | undefined;
623
+ token_filters?: {
624
+ kind: "downcase";
625
+ }[] | undefined;
932
626
  k?: number | undefined;
933
627
  m?: number | undefined;
934
628
  include_original?: boolean | undefined;
935
629
  } | undefined;
936
- ore?: {} | undefined;
937
- unique?: {
938
- token_filters?: {
939
- kind: "downcase";
940
- }[] | undefined;
941
- } | undefined;
942
630
  ste_vec?: {
943
631
  prefix: string;
944
632
  array_index_mode?: "all" | "none" | {
@@ -946,33 +634,35 @@ declare const encryptConfigSchema: z.ZodObject<{
946
634
  wildcard?: boolean | undefined;
947
635
  position?: boolean | undefined;
948
636
  } | undefined;
637
+ mode?: "standard" | "compat" | undefined;
949
638
  } | undefined;
950
639
  } | undefined;
951
640
  }>>>>>>;
952
641
  }, "strip", z.ZodTypeAny, {
953
642
  v: number;
954
643
  tables: Record<string, Record<string, {
955
- cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text";
644
+ cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
956
645
  indexes: {
957
- match?: {
646
+ ore?: {} | undefined;
647
+ ope?: {} | undefined;
648
+ unique?: {
958
649
  token_filters?: {
959
650
  kind: "downcase";
960
651
  }[] | undefined;
652
+ } | undefined;
653
+ match?: {
961
654
  tokenizer?: {
962
655
  kind: "standard";
963
656
  } | {
964
657
  kind: "ngram";
965
658
  token_length: number;
966
659
  } | undefined;
967
- k?: number | undefined;
968
- m?: number | undefined;
969
- include_original?: boolean | undefined;
970
- } | undefined;
971
- ore?: {} | undefined;
972
- unique?: {
973
660
  token_filters?: {
974
661
  kind: "downcase";
975
662
  }[] | undefined;
663
+ k?: number | undefined;
664
+ m?: number | undefined;
665
+ include_original?: boolean | undefined;
976
666
  } | undefined;
977
667
  ste_vec?: {
978
668
  prefix: string;
@@ -981,33 +671,35 @@ declare const encryptConfigSchema: z.ZodObject<{
981
671
  wildcard?: boolean | undefined;
982
672
  position?: boolean | undefined;
983
673
  } | undefined;
674
+ mode?: "standard" | "compat" | undefined;
984
675
  } | undefined;
985
676
  };
986
677
  }>>;
987
678
  }, {
988
679
  v: number;
989
680
  tables?: Record<string, Record<string, {
990
- cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text" | undefined;
681
+ cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
991
682
  indexes?: {
992
- match?: {
683
+ ore?: {} | undefined;
684
+ ope?: {} | undefined;
685
+ unique?: {
993
686
  token_filters?: {
994
687
  kind: "downcase";
995
688
  }[] | undefined;
689
+ } | undefined;
690
+ match?: {
996
691
  tokenizer?: {
997
692
  kind: "standard";
998
693
  } | {
999
694
  kind: "ngram";
1000
695
  token_length: number;
1001
696
  } | undefined;
1002
- k?: number | undefined;
1003
- m?: number | undefined;
1004
- include_original?: boolean | undefined;
1005
- } | undefined;
1006
- ore?: {} | undefined;
1007
- unique?: {
1008
697
  token_filters?: {
1009
698
  kind: "downcase";
1010
699
  }[] | undefined;
700
+ k?: number | undefined;
701
+ m?: number | undefined;
702
+ include_original?: boolean | undefined;
1011
703
  } | undefined;
1012
704
  ste_vec?: {
1013
705
  prefix: string;
@@ -1016,6 +708,7 @@ declare const encryptConfigSchema: z.ZodObject<{
1016
708
  wildcard?: boolean | undefined;
1017
709
  position?: boolean | undefined;
1018
710
  } | undefined;
711
+ mode?: "standard" | "compat" | undefined;
1019
712
  } | undefined;
1020
713
  } | undefined;
1021
714
  } | undefined> | undefined> | undefined;
@@ -1033,6 +726,7 @@ type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>;
1033
726
  type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>;
1034
727
  type UniqueIndexOpts = z.infer<typeof uniqueIndexOptsSchema>;
1035
728
  type OreIndexOpts = z.infer<typeof oreIndexOptsSchema>;
729
+ type OpeIndexOpts = z.infer<typeof opeIndexOptsSchema>;
1036
730
  type ColumnSchema = z.infer<typeof columnSchema>;
1037
731
  /**
1038
732
  * Shape of table columns: either top-level {@link EncryptedColumn} or nested
@@ -1053,323 +747,668 @@ type EncryptConfig = z.infer<typeof encryptConfigSchema>;
1053
747
  * Create with {@link encryptedField}. Use inside nested objects in {@link encryptedTable};
1054
748
  * supports `.dataType()` for plaintext type. No index methods (equality, orderAndRange, etc.).
1055
749
  */
1056
- declare class EncryptedField {
1057
- private valueName;
1058
- private castAsValue;
1059
- constructor(valueName: string);
750
+ declare class EncryptedField {
751
+ private valueName;
752
+ private castAsValue;
753
+ constructor(valueName: string);
754
+ /**
755
+ * Set or override the plaintext data type for this field.
756
+ *
757
+ * By default all values are treated as `'string'`. Use this method to specify
758
+ * a different type so the encryption layer knows how to encode the plaintext
759
+ * before encrypting.
760
+ *
761
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight.
762
+ * @returns This `EncryptedField` instance for method chaining.
763
+ *
764
+ * @example
765
+ * ```typescript
766
+ * import { encryptedField } from "@cipherstash/stack/schema"
767
+ *
768
+ * const age = encryptedField("age").dataType("number")
769
+ * ```
770
+ */
771
+ dataType(castAs: CastAs): this;
772
+ build(): {
773
+ cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
774
+ indexes: {};
775
+ };
776
+ getName(): string;
777
+ }
778
+ declare class EncryptedColumn {
779
+ private columnName;
780
+ private castAsValue;
781
+ private indexesValue;
782
+ constructor(columnName: string);
783
+ /**
784
+ * Set or override the plaintext data type for this column.
785
+ *
786
+ * By default all columns are treated as `'string'`. Use this method to specify
787
+ * a different type so the encryption layer knows how to encode the plaintext
788
+ * before encrypting.
789
+ *
790
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight.
791
+ * @returns This `EncryptedColumn` instance for method chaining.
792
+ *
793
+ * @example
794
+ * ```typescript
795
+ * import { encryptedColumn } from "@cipherstash/stack/schema"
796
+ *
797
+ * const dateOfBirth = encryptedColumn("date_of_birth").dataType("date")
798
+ * ```
799
+ */
800
+ dataType(castAs: CastAs): this;
801
+ /**
802
+ * Enable Order-Revealing Encryption (ORE) indexing on this column.
803
+ *
804
+ * ORE allows sorting, comparison, and range queries on encrypted data.
805
+ * Use with `encryptQuery` and `queryType: 'orderAndRange'`.
806
+ *
807
+ * @returns This `EncryptedColumn` instance for method chaining.
808
+ *
809
+ * @example
810
+ * ```typescript
811
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
812
+ *
813
+ * const users = encryptedTable("users", {
814
+ * email: encryptedColumn("email").orderAndRange(),
815
+ * })
816
+ * ```
817
+ */
818
+ orderAndRange(): this;
819
+ /**
820
+ * Enable an exact-match (unique) index on this column.
821
+ *
822
+ * Allows equality queries on encrypted data. Use with `encryptQuery`
823
+ * and `queryType: 'equality'`.
824
+ *
825
+ * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).
826
+ * When omitted, no token filters are applied.
827
+ * @returns This `EncryptedColumn` instance for method chaining.
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
832
+ *
833
+ * const users = encryptedTable("users", {
834
+ * email: encryptedColumn("email").equality(),
835
+ * })
836
+ * ```
837
+ */
838
+ equality(tokenFilters?: TokenFilter[]): this;
839
+ /**
840
+ * Enable a full-text / fuzzy search (match) index on this column.
841
+ *
842
+ * Uses n-gram tokenization by default for substring and fuzzy matching.
843
+ * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.
844
+ *
845
+ * @param opts - Optional match index configuration. Defaults to 3-character ngram
846
+ * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.
847
+ * @returns This `EncryptedColumn` instance for method chaining.
848
+ *
849
+ * @example
850
+ * ```typescript
851
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
852
+ *
853
+ * const users = encryptedTable("users", {
854
+ * email: encryptedColumn("email").freeTextSearch(),
855
+ * })
856
+ *
857
+ * // With custom options
858
+ * const posts = encryptedTable("posts", {
859
+ * body: encryptedColumn("body").freeTextSearch({
860
+ * tokenizer: { kind: "ngram", token_length: 4 },
861
+ * k: 8,
862
+ * m: 4096,
863
+ * }),
864
+ * })
865
+ * ```
866
+ */
867
+ freeTextSearch(opts?: MatchIndexOpts): this;
868
+ /**
869
+ * Configure this column for searchable encrypted JSON (STE-Vec).
870
+ *
871
+ * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and
872
+ * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the
873
+ * data type to `'json'`.
874
+ *
875
+ * When used with `encryptQuery`, the query operation is auto-inferred from
876
+ * the plaintext type: strings become selector queries, objects/arrays become
877
+ * containment queries.
878
+ *
879
+ * @returns This `EncryptedColumn` instance for method chaining.
880
+ *
881
+ * @example
882
+ * ```typescript
883
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
884
+ *
885
+ * const documents = encryptedTable("documents", {
886
+ * metadata: encryptedColumn("metadata").searchableJson(),
887
+ * })
888
+ * ```
889
+ */
890
+ searchableJson(): this;
891
+ build(): {
892
+ cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
893
+ indexes: {
894
+ ore?: OreIndexOpts;
895
+ ope?: OpeIndexOpts;
896
+ unique?: UniqueIndexOpts;
897
+ match?: Required<MatchIndexOpts>;
898
+ ste_vec?: SteVecIndexOpts;
899
+ };
900
+ };
901
+ getName(): string;
902
+ }
903
+ interface TableDefinition {
904
+ tableName: string;
905
+ columns: Record<string, ColumnSchema>;
906
+ }
907
+ declare class EncryptedTable<T extends EncryptedTableColumn> {
908
+ readonly tableName: string;
909
+ readonly columnBuilders: T;
910
+ /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */
911
+ readonly _columnType: T;
912
+ constructor(tableName: string, columnBuilders: T);
913
+ /**
914
+ * Compile this table schema into a `TableDefinition` used internally by the encryption client.
915
+ *
916
+ * Iterates over all column builders, calls `.build()` on each, and assembles
917
+ * the final `{ tableName, columns }` structure. For `searchableJson()` columns,
918
+ * the STE-Vec prefix is automatically set to `"<tableName>/<columnName>"`.
919
+ *
920
+ * @returns A `TableDefinition` containing the table name and built column configs.
921
+ *
922
+ * @example
923
+ * ```typescript
924
+ * const users = encryptedTable("users", {
925
+ * email: encryptedColumn("email").equality(),
926
+ * })
927
+ *
928
+ * const definition = users.build()
929
+ * // { tableName: "users", columns: { email: { cast_as: "string", indexes: { unique: ... } } } }
930
+ * ```
931
+ */
932
+ build(): TableDefinition;
933
+ }
934
+ /**
935
+ * Infer the plaintext (decrypted) type from a EncryptedTable schema.
936
+ *
937
+ * @example
938
+ * ```typescript
939
+ * const users = encryptedTable("users", {
940
+ * email: encryptedColumn("email").equality(),
941
+ * name: encryptedColumn("name"),
942
+ * })
943
+ *
944
+ * type UserPlaintext = InferPlaintext<typeof users>
945
+ * // => { email: string; name: string }
946
+ * ```
947
+ */
948
+ type InferPlaintext<T extends EncryptedTable<any>> = T extends EncryptedTable<infer C> ? {
949
+ [K in keyof C as C[K] extends EncryptedColumn | EncryptedField ? K : never]: string;
950
+ } : never;
951
+ /**
952
+ * Infer the encrypted type from a EncryptedTable schema.
953
+ *
954
+ * @example
955
+ * ```typescript
956
+ * const users = encryptedTable("users", {
957
+ * email: encryptedColumn("email").equality(),
958
+ * })
959
+ *
960
+ * type UserEncrypted = InferEncrypted<typeof users>
961
+ * // => { email: Encrypted }
962
+ * ```
963
+ */
964
+ type InferEncrypted<T extends EncryptedTable<any>> = T extends EncryptedTable<infer C> ? {
965
+ [K in keyof C as C[K] extends EncryptedColumn | EncryptedField ? K : never]: Encrypted;
966
+ } : never;
967
+ /**
968
+ * Define an encrypted table schema.
969
+ *
970
+ * Creates a `EncryptedTable` that maps a database table name to a set of encrypted
971
+ * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`
972
+ * when initializing the client.
973
+ *
974
+ * The returned object is also a proxy that exposes each column builder directly,
975
+ * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,
976
+ * and `encryptQuery`.
977
+ *
978
+ * @param tableName - The name of the database table this schema represents.
979
+ * @param columns - An object whose keys are logical column names and values are
980
+ * {@link EncryptedColumn} from {@link encryptedColumn}, or nested objects whose
981
+ * leaves are {@link EncryptedField} from {@link encryptedField}.
982
+ * @returns A `EncryptedTable<T> & T` that can be used as both a schema definition
983
+ * and a column accessor.
984
+ *
985
+ * @example
986
+ * ```typescript
987
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
988
+ *
989
+ * const users = encryptedTable("users", {
990
+ * email: encryptedColumn("email").equality().freeTextSearch(),
991
+ * address: encryptedColumn("address"),
992
+ * })
993
+ *
994
+ * // Use as schema
995
+ * const client = await Encryption({ schemas: [users] })
996
+ *
997
+ * // Use as column accessor
998
+ * await client.encrypt("hello@example.com", { column: users.email, table: users })
999
+ * ```
1000
+ */
1001
+ declare function encryptedTable<T extends EncryptedTableColumn>(tableName: string, columns: T): EncryptedTable<T> & T;
1002
+ /**
1003
+ * Define an encrypted column within a table schema.
1004
+ *
1005
+ * Creates a `EncryptedColumn` builder for the given column name. Chain index
1006
+ * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,
1007
+ * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption
1008
+ * and the plaintext data type.
1009
+ *
1010
+ * @param columnName - The name of the database column to encrypt.
1011
+ * @returns A new `EncryptedColumn` builder.
1012
+ *
1013
+ * @example
1014
+ * ```typescript
1015
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1016
+ *
1017
+ * const users = encryptedTable("users", {
1018
+ * email: encryptedColumn("email").equality().freeTextSearch().orderAndRange(),
1019
+ * })
1020
+ * ```
1021
+ */
1022
+ declare function encryptedColumn(columnName: string): EncryptedColumn;
1023
+ /**
1024
+ * Define an encrypted field for use in nested or structured schemas.
1025
+ *
1026
+ * `encryptedField` is similar to {@link encryptedColumn} but creates an {@link EncryptedField}
1027
+ * for nested fields that are encrypted but not searchable (no indexes). Use `.dataType()`
1028
+ * to specify the plaintext type.
1029
+ *
1030
+ * @param valueName - The name of the value field.
1031
+ * @returns A new `EncryptedField` builder.
1032
+ *
1033
+ * @example
1034
+ * ```typescript
1035
+ * import { encryptedTable, encryptedField } from "@cipherstash/stack/schema"
1036
+ *
1037
+ * const orders = encryptedTable("orders", {
1038
+ * details: {
1039
+ * amount: encryptedField("amount").dataType("number"),
1040
+ * currency: encryptedField("currency"),
1041
+ * },
1042
+ * })
1043
+ * ```
1044
+ */
1045
+ declare function encryptedField(valueName: string): EncryptedField;
1046
+ /**
1047
+ * Build an encrypt config from a list of encrypted tables.
1048
+ *
1049
+ * @param protectTables - The list of encrypted tables to build the config from.
1050
+ * @returns An encrypt config object.
1051
+ *
1052
+ * @example
1053
+ * ```typescript
1054
+ * import { buildEncryptConfig } from "@cipherstash/stack/schema"
1055
+ *
1056
+ * const users = encryptedTable("users", {
1057
+ * email: encryptedColumn("email").equality(),
1058
+ * })
1059
+ *
1060
+ * const orders = encryptedTable("orders", {
1061
+ * amount: encryptedColumn("amount").dataType("number"),
1062
+ * })
1063
+ *
1064
+ * const config = buildEncryptConfig(users, orders)
1065
+ * console.log(config)
1066
+ * ```
1067
+ */
1068
+ declare function buildEncryptConfig(...protectTables: Array<BuildableTable>): EncryptConfig;
1069
+
1070
+ /** Brand symbol for nominal typing */
1071
+ declare const __brand: unique symbol;
1072
+ /** Creates a branded type that is structurally incompatible with the base type */
1073
+ type Brand<T, B extends string> = T & {
1074
+ readonly [__brand]: B;
1075
+ };
1076
+ type Client = Awaited<ReturnType<typeof newClient>> | undefined;
1077
+ /** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */
1078
+ type EncryptedValue = Brand<Encrypted$1, 'encrypted'>;
1079
+ /** Structural type representing encrypted data stored in the database. Always
1080
+ * carries a ciphertext. Covers BOTH wire formats: the EQL v2.3 payloads
1081
+ * (`k: "ct"` / `k: "sv"`) and the EQL v3 payloads (flat `{v: 3, i, c, …}`
1082
+ * scalars and `{v: 3, k: "sv", i, sv}` SteVec documents). Which format
1083
+ * `encrypt` produces is selected by the client's
1084
+ * {@link ClientConfig.eqlVersion}; `decrypt` accepts both regardless.
1085
+ * v3 scalars carry no `k` discriminator, so narrow with `'k' in payload`
1086
+ * before reading it. See also `EncryptedValue` for branded nominal typing,
1087
+ * and {@link EncryptedQuery} for the search-term shape returned by
1088
+ * `encryptQuery`. */
1089
+ type Encrypted = EncryptedPayload;
1090
+ /** Structural type representing an encrypted query term (search needle)
1091
+ * returned by `encryptQuery` / `encryptQueryBulk` for scalar
1092
+ * (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path
1093
+ * queries, plus — under `eqlVersion: 3` — the `eql_v3.jsonb_query`
1094
+ * containment needle. Carries no ciphertext — matched against stored
1095
+ * values, never decrypted. v2 JSON containment queries (`ste_vec_term`)
1096
+ * return a storage-shaped {@link Encrypted} payload instead. */
1097
+ type EncryptedQuery = EncryptedQuery$1 | EncryptedV3Query;
1098
+ /**
1099
+ * Plaintext values the SDK accepts for encryption.
1100
+ *
1101
+ * Widens the FFI's `JsPlaintext` (`string | number | boolean |
1102
+ * Record<string, unknown> | JsPlaintext[]`) with `Date` and `bigint`. `Date`
1103
+ * is a supported cast target that is omitted from the FFI's `JsPlaintext` INPUT
1104
+ * union, but it serializes at the boundary via `toJSON` (ISO string), so it is
1105
+ * accepted on the way in.
1106
+ *
1107
+ * `bigint` is the plaintext for the v3 int8/bigint domains (see `eql/v3`),
1108
+ * which always decrypt to a JS `bigint`. protect-ffi 0.28 marshals a native
1109
+ * `bigint` across the Neon boundary losslessly. i64 bounds
1110
+ * (`-2^63 … 2^63 - 1`) are enforced at the protect-ffi boundary, not here —
1111
+ * out-of-range values surface as encryption errors from the FFI.
1112
+ *
1113
+ * When the upstream FFI `JsPlaintext` includes `Date` and `bigint`, both extra
1114
+ * arms can collapse back into `JsPlaintext`.
1115
+ */
1116
+ type Plaintext = JsPlaintext | Date | bigint;
1117
+ type KeysetIdentifier = {
1118
+ name: string;
1119
+ } | {
1120
+ id: string;
1121
+ };
1122
+ type ClientConfig = {
1060
1123
  /**
1061
- * Set or override the plaintext data type for this field.
1062
- *
1063
- * By default all values are treated as `'string'`. Use this method to specify
1064
- * a different type so the encryption layer knows how to encode the plaintext
1065
- * before encrypting.
1066
- *
1067
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.
1068
- * @returns This `EncryptedField` instance for method chaining.
1069
- *
1070
- * @example
1071
- * ```typescript
1072
- * import { encryptedField } from "@cipherstash/stack/schema"
1073
- *
1074
- * const age = encryptedField("age").dataType("number")
1075
- * ```
1124
+ * The CipherStash workspace CRN (Cloud Resource Name).
1125
+ * Format: `crn:<region>.aws:<workspace-id>`.
1126
+ * Can also be set via the `CS_WORKSPACE_CRN` environment variable.
1076
1127
  */
1077
- dataType(castAs: CastAs): this;
1078
- build(): {
1079
- cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text";
1080
- indexes: {};
1081
- };
1082
- getName(): string;
1083
- }
1084
- declare class EncryptedColumn {
1085
- private columnName;
1086
- private castAsValue;
1087
- private indexesValue;
1088
- constructor(columnName: string);
1128
+ workspaceCrn?: string;
1089
1129
  /**
1090
- * Set or override the plaintext data type for this column.
1091
- *
1092
- * By default all columns are treated as `'string'`. Use this method to specify
1093
- * a different type so the encryption layer knows how to encode the plaintext
1094
- * before encrypting.
1095
- *
1096
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
1097
- * @returns This `EncryptedColumn` instance for method chaining.
1098
- *
1099
- * @example
1100
- * ```typescript
1101
- * import { encryptedColumn } from "@cipherstash/stack/schema"
1102
- *
1103
- * const dateOfBirth = encryptedColumn("date_of_birth").dataType("date")
1104
- * ```
1130
+ * The API access key used for authenticating with the CipherStash API.
1131
+ * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.
1132
+ * Obtain this from the CipherStash dashboard after creating a workspace.
1105
1133
  */
1106
- dataType(castAs: CastAs): this;
1134
+ accessKey?: string;
1107
1135
  /**
1108
- * Enable Order-Revealing Encryption (ORE) indexing on this column.
1109
- *
1110
- * ORE allows sorting, comparison, and range queries on encrypted data.
1111
- * Use with `encryptQuery` and `queryType: 'orderAndRange'`.
1112
- *
1113
- * @returns This `EncryptedColumn` instance for method chaining.
1114
- *
1115
- * @example
1116
- * ```typescript
1117
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1118
- *
1119
- * const users = encryptedTable("users", {
1120
- * email: encryptedColumn("email").orderAndRange(),
1121
- * })
1122
- * ```
1136
+ * The client identifier used to authenticate with CipherStash services.
1137
+ * Can also be set via the `CS_CLIENT_ID` environment variable.
1138
+ * Generated during workspace onboarding in the CipherStash dashboard.
1123
1139
  */
1124
- orderAndRange(): this;
1140
+ clientId?: string;
1125
1141
  /**
1126
- * Enable an exact-match (unique) index on this column.
1127
- *
1128
- * Allows equality queries on encrypted data. Use with `encryptQuery`
1129
- * and `queryType: 'equality'`.
1130
- *
1131
- * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).
1132
- * When omitted, no token filters are applied.
1133
- * @returns This `EncryptedColumn` instance for method chaining.
1134
- *
1135
- * @example
1136
- * ```typescript
1137
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1138
- *
1139
- * const users = encryptedTable("users", {
1140
- * email: encryptedColumn("email").equality(),
1141
- * })
1142
- * ```
1142
+ * The client key material used in combination with ZeroKMS for encryption operations.
1143
+ * Can also be set via the `CS_CLIENT_KEY` environment variable.
1144
+ * Generated during workspace onboarding in the CipherStash dashboard.
1143
1145
  */
1144
- equality(tokenFilters?: TokenFilter[]): this;
1146
+ clientKey?: string;
1145
1147
  /**
1146
- * Enable a full-text / fuzzy search (match) index on this column.
1147
- *
1148
- * Uses n-gram tokenization by default for substring and fuzzy matching.
1149
- * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.
1148
+ * An optional keyset identifier for multi-tenant encryption.
1149
+ * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.
1150
+ * Specify by name (`{ name: "tenant-a" }`) or UUID (`{ id: "..." }`).
1151
+ * Keysets are created and managed in the
1152
+ * [dashboard](https://dashboard.cipherstash.com/workspaces/_/keysets); omit to
1153
+ * use the workspace's default keyset. A client is bound to one keyset for its
1154
+ * lifetime, so use one client per tenant.
1150
1155
  *
1151
- * @param opts - Optional match index configuration. Defaults to 3-character ngram
1152
- * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.
1153
- * @returns This `EncryptedColumn` instance for method chaining.
1156
+ * @see {@link Encryption} for the full keysets walkthrough.
1157
+ */
1158
+ keyset?: KeysetIdentifier;
1159
+ /**
1160
+ * An optional authentication strategy for ZeroKMS requests, from
1161
+ * `@cipherstash/auth` (re-exported by `@cipherstash/stack`). When provided,
1162
+ * its `getToken()` is invoked on every ZeroKMS request and takes precedence
1163
+ * over the default `auto` strategy (the `clientKey` is still required for
1164
+ * encryption). Use:
1154
1165
  *
1155
- * @example
1156
- * ```typescript
1157
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1166
+ * - `OidcFederationStrategy` for per-user, identity-bound encryption —
1167
+ * federates an end user's OIDC JWT into a CTS service token, so requests
1168
+ * authenticate as that user. Pair with `.withLockContext({ identityClaim })`
1169
+ * to bind the data key to a claim. This replaces the older
1170
+ * `LockContext.identify()` ceremony.
1171
+ * - `AccessKeyStrategy` for service-to-service / CI, or any custom
1172
+ * `{ getToken() }` object for bespoke token acquisition / caching.
1158
1173
  *
1159
- * const users = encryptedTable("users", {
1160
- * email: encryptedColumn("email").freeTextSearch(),
1161
- * })
1174
+ * Leave unset to use the default `auto` strategy, which reads credentials
1175
+ * from the `CS_*` environment variables and falls back to the local dev
1176
+ * profile created by `npx stash auth login`.
1162
1177
  *
1163
- * // With custom options
1164
- * const posts = encryptedTable("posts", {
1165
- * body: encryptedColumn("body").freeTextSearch({
1166
- * tokenizer: { kind: "ngram", token_length: 4 },
1167
- * k: 8,
1168
- * m: 4096,
1169
- * }),
1170
- * })
1171
- * ```
1178
+ * @see {@link AuthStrategy}
1179
+ * @see {@link Encryption} for a full walkthrough of the authentication options.
1172
1180
  */
1173
- freeTextSearch(opts?: MatchIndexOpts): this;
1181
+ authStrategy?: AuthStrategy;
1174
1182
  /**
1175
- * Configure this column for searchable encrypted JSON (STE-Vec).
1176
- *
1177
- * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and
1178
- * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the
1179
- * data type to `'json'`.
1183
+ * @deprecated Renamed to {@link ClientConfig.authStrategy}. Still honoured for
1184
+ * backwards compatibility — passing it logs a deprecation warning at runtime —
1185
+ * but it will be removed in a future release. Set `authStrategy` instead.
1186
+ */
1187
+ strategy?: AuthStrategy;
1188
+ /**
1189
+ * The EQL wire version the client emits — one FFI client always emits
1190
+ * exactly one wire format.
1180
1191
  *
1181
- * When used with `encryptQuery`, the query operation is auto-inferred from
1182
- * the plaintext type: strings become selector queries, objects/arrays become
1183
- * containment queries.
1192
+ * - `2` (the protect-ffi default): payloads target the
1193
+ * `eql_v2_encrypted` column type.
1194
+ * - `3`: payloads target the per-capability `eql_v3` domains
1195
+ * (`eql_v3.text_eq`, `eql_v3.integer_ord_ore`, `eql_v3.json`, …),
1196
+ * derived from each column's `cast_as` and indexes.
1184
1197
  *
1185
- * @returns This `EncryptedColumn` instance for method chaining.
1198
+ * When omitted, {@link Encryption} auto-detects from the schema set:
1199
+ * EQL v3 tables (from `@cipherstash/stack/v3`, marked by
1200
+ * `buildColumnKeyMap()`) select `3`; v2 tables leave the FFI default
1201
+ * (`2`) untouched. Mixing v2 and v3 tables in one client is an error —
1202
+ * split them across two clients instead.
1186
1203
  *
1187
- * @example
1188
- * ```typescript
1189
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1204
+ * `decrypt` accepts BOTH formats regardless of this setting, so v2 and
1205
+ * v3 data can coexist during a migration.
1190
1206
  *
1191
- * const documents = encryptedTable("documents", {
1192
- * metadata: encryptedColumn("metadata").searchableJson(),
1193
- * })
1194
- * ```
1207
+ * Under `3`, `encryptQuery` returns EQL v3 query operands (protect-ffi
1208
+ * 0.29+): term-only scalar operands for the `eql_v3.query_<name>` twins,
1209
+ * the `eql_v3.query_jsonb` containment needle, and bare selector-hash
1210
+ * strings for JSON path queries.
1195
1211
  */
1196
- searchableJson(): this;
1197
- build(): {
1198
- cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "timestamp" | "json" | "text";
1199
- indexes: {
1200
- ore?: OreIndexOpts;
1201
- unique?: UniqueIndexOpts;
1202
- match?: Required<MatchIndexOpts>;
1203
- ste_vec?: SteVecIndexOpts;
1204
- };
1205
- };
1212
+ eqlVersion?: 2 | 3;
1213
+ };
1214
+ type AtLeastOneCsTable<T> = [T, ...T[]];
1215
+ /** Structural contract for a column builder the client can consume for STORAGE
1216
+ * (`encrypt`). Satisfied by v2 `EncryptedColumn` / `EncryptedField` AND v3
1217
+ * `EncryptedTextSearchColumn` — fields ARE encryptable, so this stays wide. */
1218
+ interface BuildableColumn {
1206
1219
  getName(): string;
1220
+ build(): ColumnSchema;
1207
1221
  }
1208
- interface TableDefinition {
1209
- tableName: string;
1210
- columns: Record<string, ColumnSchema>;
1222
+ /** Structural contract for a column the client can consume for QUERIES
1223
+ * (`encryptQuery` / search terms). Narrower than `BuildableColumn`: it must
1224
+ * EXCLUDE non-queryable `EncryptedField` (a field has no indexes). A v2
1225
+ * `EncryptedColumn` qualifies via the nominal arm; a v3 queryable concrete
1226
+ * type qualifies via the `getEqlType()` structural arm; `EncryptedField` (no
1227
+ * `getEqlType`, not an `EncryptedColumn`) is rejected. */
1228
+ interface BuildableV3QueryableColumn extends BuildableColumn {
1229
+ getEqlType(): string;
1230
+ getQueryCapabilities(): {
1231
+ equality: boolean;
1232
+ orderAndRange: boolean;
1233
+ freeTextSearch: boolean;
1234
+ };
1235
+ isQueryable(): true;
1211
1236
  }
1212
- declare class EncryptedTable<T extends EncryptedTableColumn> {
1213
- readonly tableName: string;
1214
- readonly columnBuilders: T;
1215
- /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */
1216
- readonly _columnType: T;
1217
- constructor(tableName: string, columnBuilders: T);
1237
+ type BuildableQueryColumn = EncryptedColumn | BuildableV3QueryableColumn;
1238
+ /** Structural contract for a table builder the client can consume. Satisfied by
1239
+ * v2 and v3 `EncryptedTable` alike. */
1240
+ interface BuildableTable {
1241
+ tableName: string;
1242
+ build(): {
1243
+ tableName: string;
1244
+ columns: Record<string, ColumnSchema>;
1245
+ };
1218
1246
  /**
1219
- * Compile this table schema into a `TableDefinition` used internally by the encryption client.
1220
- *
1221
- * Iterates over all column builders, calls `.build()` on each, and assembles
1222
- * the final `{ tableName, columns }` structure. For `searchableJson()` columns,
1223
- * the STE-Vec prefix is automatically set to `"<tableName>/<columnName>"`.
1224
- *
1225
- * @returns A `TableDefinition` containing the table name and built column configs.
1226
- *
1227
- * @example
1228
- * ```typescript
1229
- * const users = encryptedTable("users", {
1230
- * email: encryptedColumn("email").equality(),
1231
- * })
1247
+ * Optional map from a model field's JS property name to its encrypt-config
1248
+ * column name (the DB name). Present when the two can differ — v3 tables key
1249
+ * their config by DB name (`column.getName()`) while models are written with
1250
+ * JS property keys, so the model path must match by property but address the
1251
+ * FFI/config by DB name.
1232
1252
  *
1233
- * const definition = users.build()
1234
- * // { tableName: "users", columns: { email: { cast_as: "string", indexes: { unique: ... } } } }
1235
- * ```
1253
+ * Absent on v2 tables, whose `build()` already keys columns by the JS property
1254
+ * name; the model path then matches and addresses by that same key.
1236
1255
  */
1237
- build(): TableDefinition;
1256
+ buildColumnKeyMap?(): Record<string, string>;
1238
1257
  }
1258
+ type EncryptionClientConfig = {
1259
+ schemas: AtLeastOneCsTable<BuildableTable>;
1260
+ config?: ClientConfig;
1261
+ };
1239
1262
  /**
1240
- * Infer the plaintext (decrypted) type from a EncryptedTable schema.
1263
+ * The literal column map of a buildable table, read from its type-level
1264
+ * `_columnType` brand. Both v2 and v3 `EncryptedTable` carry this brand, so this
1265
+ * recovers the literal column keys structurally.
1241
1266
  *
1242
- * @example
1243
- * ```typescript
1244
- * const users = encryptedTable("users", {
1245
- * email: encryptedColumn("email").equality(),
1246
- * name: encryptedColumn("name"),
1247
- * })
1267
+ * This deliberately uses the `_columnType` brand rather than `build().columns`:
1268
+ * `BuildableTable.build()` is typed to return `Record<string, ColumnSchema>`,
1269
+ * which erases the literal keys and would mark EVERY model field as encrypted.
1248
1270
  *
1249
- * type UserPlaintext = InferPlaintext<typeof users>
1250
- * // => { email: string; name: string }
1251
- * ```
1271
+ * The fallbacks resolve to `Record<never, never>` (a no-key type), NOT `never`:
1272
+ * a value typed as the bare structural `BuildableTable` carries no `_columnType`
1273
+ * brand, and `keyof never` is `string | number | symbol` — which would wrongly
1274
+ * mark EVERY model field as encrypted. `keyof Record<never, never>` is `never`,
1275
+ * so `EncryptedFromBuildableTable` degrades gracefully to the model unchanged.
1252
1276
  */
1253
- type InferPlaintext<T extends EncryptedTable<any>> = T extends EncryptedTable<infer C> ? {
1254
- [K in keyof C as C[K] extends EncryptedColumn | EncryptedField ? K : never]: string;
1255
- } : never;
1277
+ type BuildableTableColumns<T extends BuildableTable> = T extends {
1278
+ readonly _columnType: infer C;
1279
+ } ? C extends Record<string, unknown> ? C : Record<never, never> : Record<never, never>;
1256
1280
  /**
1257
- * Infer the encrypted type from a EncryptedTable schema.
1258
- *
1259
- * @example
1260
- * ```typescript
1261
- * const users = encryptedTable("users", {
1262
- * email: encryptedColumn("email").equality(),
1263
- * })
1281
+ * Maps a plaintext model type to its encrypted form using a buildable table.
1264
1282
  *
1265
- * type UserEncrypted = InferEncrypted<typeof users>
1266
- * // => { email: Encrypted }
1267
- * ```
1283
+ * Fields whose keys match a column defined in `Table` (via its `_columnType`
1284
+ * brand) become `Encrypted` (`Encrypted | null` when the source field is
1285
+ * nullable); all other fields retain their original types from `T`. Works for
1286
+ * both v2 and v3 tables. See {@link EncryptedFromSchema} for the v2-specific
1287
+ * variant retained for backward compatibility.
1268
1288
  */
1269
- type InferEncrypted<T extends EncryptedTable<any>> = T extends EncryptedTable<infer C> ? {
1270
- [K in keyof C as C[K] extends EncryptedColumn | EncryptedField ? K : never]: Encrypted;
1271
- } : never;
1289
+ type EncryptedFromBuildableTable<T, Table extends BuildableTable> = {
1290
+ [K in keyof T]: [K] extends [keyof BuildableTableColumns<Table>] ? null extends T[K] ? Encrypted | null : Encrypted : T[K];
1291
+ };
1272
1292
  /**
1273
- * Define an encrypted table schema.
1274
- *
1275
- * Creates a `EncryptedTable` that maps a database table name to a set of encrypted
1276
- * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`
1277
- * when initializing the client.
1278
- *
1279
- * The returned object is also a proxy that exposes each column builder directly,
1280
- * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,
1281
- * and `encryptQuery`.
1282
- *
1283
- * @param tableName - The name of the database table this schema represents.
1284
- * @param columns - An object whose keys are logical column names and values are
1285
- * {@link EncryptedColumn} from {@link encryptedColumn}, or nested objects whose
1286
- * leaves are {@link EncryptedField} from {@link encryptedField}.
1287
- * @returns A `EncryptedTable<T> & T` that can be used as both a schema definition
1288
- * and a column accessor.
1289
- *
1290
- * @example
1291
- * ```typescript
1292
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1293
- *
1294
- * const users = encryptedTable("users", {
1295
- * email: encryptedColumn("email").equality().freeTextSearch(),
1296
- * address: encryptedColumn("address"),
1297
- * })
1298
- *
1299
- * // Use as schema
1300
- * const client = await Encryption({ schemas: [users] })
1301
- *
1302
- * // Use as column accessor
1303
- * await client.encrypt("hello@example.com", { column: users.email, table: users })
1304
- * ```
1293
+ * Options for single-value encrypt operations.
1294
+ * Use a column from your table schema (from {@link encryptedColumn}) or a nested
1295
+ * field (from {@link encryptedField}) as the target for encryption.
1305
1296
  */
1306
- declare function encryptedTable<T extends EncryptedTableColumn>(tableName: string, columns: T): EncryptedTable<T> & T;
1297
+ type EncryptOptions = {
1298
+ /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */
1299
+ column: BuildableColumn;
1300
+ table: BuildableTable;
1301
+ };
1302
+ /** Format for encrypted query/search term return values */
1303
+ type EncryptedReturnType = 'eql' | 'composite-literal' | 'escaped-composite-literal';
1304
+ type SearchTerm = {
1305
+ value: Plaintext;
1306
+ column: BuildableQueryColumn;
1307
+ table: BuildableTable;
1308
+ returnType?: EncryptedReturnType;
1309
+ };
1310
+ /** Encrypted search term result. `eql` return type yields either a storage
1311
+ * payload (`Encrypted`, for `ste_vec_term`) or a query-only term
1312
+ * (`EncryptedQuery`, for scalar lookups and `ste_vec_selector`); the
1313
+ * `composite-literal` return types yield a string. */
1314
+ type EncryptedSearchTerm = Encrypted | EncryptedQuery | string;
1315
+ /** Result of encryptQuery (single or batch). `eql` return type yields either a
1316
+ * storage payload (`Encrypted`) or a query-only term (`EncryptedQuery`); the
1317
+ * `composite-literal` return types yield a string. */
1318
+ type EncryptedQueryResult = Encrypted | EncryptedQuery | string | null;
1319
+ type EncryptedFields<T> = {
1320
+ [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K];
1321
+ };
1322
+ type OtherFields<T> = {
1323
+ [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K];
1324
+ };
1325
+ type DecryptedFields<T> = {
1326
+ [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: null extends T[K] ? string | null : string;
1327
+ };
1328
+ /** Model with encrypted fields replaced by plaintext (decrypted) values */
1329
+ type Decrypted<T> = OtherFields<T> & DecryptedFields<T>;
1307
1330
  /**
1308
- * Define an encrypted column within a table schema.
1331
+ * Maps a plaintext model type to its encrypted form using the table schema.
1309
1332
  *
1310
- * Creates a `EncryptedColumn` builder for the given column name. Chain index
1311
- * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,
1312
- * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption
1313
- * and the plaintext data type.
1333
+ * Fields whose keys match columns defined in `S` become `Encrypted`;
1334
+ * all other fields retain their original types from `T`.
1314
1335
  *
1315
- * @param columnName - The name of the database column to encrypt.
1316
- * @returns A new `EncryptedColumn` builder.
1336
+ * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an
1337
+ * explicit `<User>` type argument without specifying `S`), the type degrades
1338
+ * gracefully to `T` — preserving backward compatibility.
1339
+ *
1340
+ * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)
1341
+ * @typeParam S - The table schema column definition, inferred from the `table` argument
1317
1342
  *
1318
1343
  * @example
1319
1344
  * ```typescript
1320
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
1321
- *
1322
- * const users = encryptedTable("users", {
1323
- * email: encryptedColumn("email").equality().freeTextSearch().orderAndRange(),
1324
- * })
1345
+ * type User = { id: string; email: string }
1346
+ * // With a schema that defines `email`:
1347
+ * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>
1348
+ * // => { id: string; email: Encrypted }
1325
1349
  * ```
1326
1350
  */
1327
- declare function encryptedColumn(columnName: string): EncryptedColumn;
1351
+ type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {
1352
+ [K in keyof T]: [K] extends [keyof S] ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField] ? null extends T[K] ? Encrypted | null : Encrypted : T[K] : T[K];
1353
+ };
1354
+ type BulkEncryptPayload = Array<{
1355
+ id?: string;
1356
+ plaintext: Plaintext | null;
1357
+ }>;
1358
+ type BulkEncryptedData = Array<{
1359
+ id?: string;
1360
+ data: Encrypted | null;
1361
+ }>;
1362
+ type BulkDecryptPayload = Array<{
1363
+ id?: string;
1364
+ data: Encrypted | null;
1365
+ }>;
1366
+ type BulkDecryptedData = Array<DecryptionResult<JsPlaintext | null>>;
1367
+ type DecryptionSuccess<T> = {
1368
+ error?: never;
1369
+ data: T;
1370
+ id?: string;
1371
+ };
1372
+ type DecryptionError<T> = {
1373
+ error: T;
1374
+ id?: string;
1375
+ data?: never;
1376
+ };
1328
1377
  /**
1329
- * Define an encrypted field for use in nested or structured schemas.
1330
- *
1331
- * `encryptedField` is similar to {@link encryptedColumn} but creates an {@link EncryptedField}
1332
- * for nested fields that are encrypted but not searchable (no indexes). Use `.dataType()`
1333
- * to specify the plaintext type.
1334
- *
1335
- * @param valueName - The name of the value field.
1336
- * @returns A new `EncryptedField` builder.
1337
- *
1338
- * @example
1339
- * ```typescript
1340
- * import { encryptedTable, encryptedField } from "@cipherstash/stack/schema"
1341
- *
1342
- * const orders = encryptedTable("orders", {
1343
- * details: {
1344
- * amount: encryptedField("amount").dataType("number"),
1345
- * currency: encryptedField("currency"),
1346
- * },
1347
- * })
1348
- * ```
1378
+ * Result type for individual items in bulk decrypt operations.
1379
+ * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations
1380
+ * can have per-item failures.
1349
1381
  */
1350
- declare function encryptedField(valueName: string): EncryptedField;
1382
+ type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>;
1351
1383
  /**
1352
- * Build an encrypt config from a list of encrypted tables.
1353
- *
1354
- * @param protectTables - The list of encrypted tables to build the config from.
1355
- * @returns An encrypt config object.
1356
- *
1357
- * @example
1358
- * ```typescript
1359
- * import { buildEncryptConfig } from "@cipherstash/stack/schema"
1360
- *
1361
- * const users = encryptedTable("users", {
1362
- * email: encryptedColumn("email").equality(),
1363
- * })
1364
- *
1365
- * const orders = encryptedTable("orders", {
1366
- * amount: encryptedColumn("amount").dataType("number"),
1367
- * })
1384
+ * User-facing query type names for encrypting query values.
1368
1385
  *
1369
- * const config = buildEncryptConfig(users, orders)
1370
- * console.log(config)
1371
- * ```
1386
+ * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
1387
+ * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
1388
+ * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)
1389
+ * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)
1390
+ * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)
1391
+ * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)
1372
1392
  */
1373
- declare function buildEncryptConfig(...protectTables: Array<BuildableTable>): EncryptConfig;
1393
+ type QueryTypeName = 'orderAndRange' | 'freeTextSearch' | 'equality' | 'steVecSelector' | 'steVecTerm' | 'searchableJson';
1394
+ declare const queryTypes: {
1395
+ readonly orderAndRange: "orderAndRange";
1396
+ readonly freeTextSearch: "freeTextSearch";
1397
+ readonly equality: "equality";
1398
+ readonly steVecSelector: "steVecSelector";
1399
+ readonly steVecTerm: "steVecTerm";
1400
+ readonly searchableJson: "searchableJson";
1401
+ };
1402
+ /** @internal */
1403
+ type QueryTermBase = {
1404
+ column: BuildableQueryColumn;
1405
+ table: BuildableTable;
1406
+ queryType?: QueryTypeName;
1407
+ returnType?: EncryptedReturnType;
1408
+ };
1409
+ type EncryptQueryOptions = QueryTermBase;
1410
+ type ScalarQueryTerm = QueryTermBase & {
1411
+ value: Plaintext;
1412
+ };
1374
1413
 
1375
- export { type OtherFields as $, type SteVecIndexOpts as A, type BulkEncryptPayload as B, type ClientConfig as C, type Decrypted as D, type EncryptedReturnType as E, buildEncryptConfig as F, castAsEnum as G, encryptConfigSchema as H, type InferEncrypted as I, eqlCastAsEnum as J, type KeysetIdentifier as K, toEqlCastAs as L, type MatchIndexOpts as M, type BuildableTableColumns as N, type OreIndexOpts as O, type Plaintext as P, type QueryTypeName as Q, type BuildableV3QueryableColumn as R, type ScalarQueryTerm as S, type TokenFilter as T, type UniqueIndexOpts as U, type DecryptedFields as V, type DecryptionResult as W, type EncryptedFields as X, type EncryptedFromSchema as Y, type EncryptedQuery as Z, type EncryptedSearchTerm as _, type Encrypted as a, type SearchTerm as a0, queryTypes as a1, type EncryptOptions as b, type BulkDecryptPayload as c, encryptedField as d, encryptedColumn as e, encryptedTable as f, EncryptedTable as g, type EncryptedTableColumn as h, type ColumnSchema as i, type EncryptConfig as j, EncryptedColumn as k, type CastAs as l, type EncryptedValue as m, type EncryptedQueryResult as n, type Client as o, type BulkDecryptedData as p, type BulkEncryptedData as q, type BuildableColumn as r, type BuildableTable as s, type EncryptQueryOptions as t, type BuildableQueryColumn as u, type EncryptedFromBuildableTable as v, type EncryptionClientConfig as w, EncryptedField as x, type InferPlaintext as y, type EqlCastAs as z };
1414
+ export { encryptedTable as $, type EncryptedTableColumn as A, type BuildableColumn as B, type CastAs as C, type Decrypted as D, type EncryptConfig as E, type EncryptedValue as F, type EncryptionClientConfig as G, type EqlCastAs as H, type InferEncrypted as I, type InferPlaintext as J, type KeysetIdentifier as K, type OreIndexOpts as L, type MatchIndexOpts as M, type OtherFields as N, type OpeIndexOpts as O, type Plaintext as P, type QueryTypeName as Q, type SearchTerm as R, type ScalarQueryTerm as S, type SteVecIndexOpts as T, type TokenFilter as U, type UniqueIndexOpts as V, buildEncryptConfig as W, castAsEnum as X, encryptConfigSchema as Y, encryptedColumn as Z, encryptedField as _, type BuildableQueryColumn as a, eqlCastAsEnum as a0, queryTypes as a1, toEqlCastAs as a2, type BuildableTable as b, type BuildableTableColumns as c, type BuildableV3QueryableColumn as d, type BulkDecryptPayload as e, type BulkDecryptedData as f, type BulkEncryptPayload as g, type BulkEncryptedData as h, type Client as i, type ClientConfig as j, type ColumnSchema as k, type DecryptedFields as l, type DecryptionResult as m, type EncryptOptions as n, type EncryptQueryOptions as o, type Encrypted as p, EncryptedColumn as q, EncryptedField as r, type EncryptedFields as s, type EncryptedFromBuildableTable as t, type EncryptedFromSchema as u, type EncryptedQuery as v, type EncryptedQueryResult as w, type EncryptedReturnType as x, type EncryptedSearchTerm as y, EncryptedTable as z };