@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.
- package/CHANGELOG.md +596 -0
- package/README.md +376 -276
- package/dist/adapter-kit.cjs +1002 -0
- package/dist/adapter-kit.cjs.map +1 -0
- package/dist/adapter-kit.d.cts +120 -0
- package/dist/adapter-kit.d.ts +120 -0
- package/dist/adapter-kit.js +122 -0
- package/dist/adapter-kit.js.map +1 -0
- package/dist/base-operation-AOAIvsSB.d.cts +32 -0
- package/dist/base-operation-FXEzUXIq.d.ts +32 -0
- package/dist/{chunk-4AVL4VZD.js → chunk-3B5ZX3IS.js} +3 -1
- package/dist/chunk-3B5ZX3IS.js.map +1 -0
- package/dist/{chunk-U66S7VIF.js → chunk-6SGN52W6.js} +166 -107
- package/dist/chunk-6SGN52W6.js.map +1 -0
- package/dist/chunk-7333ZC6L.js +48 -0
- package/dist/chunk-7333ZC6L.js.map +1 -0
- package/dist/{chunk-MP3SSDNN.js → chunk-CLM7E4I6.js} +15 -15
- package/dist/{chunk-MP3SSDNN.js.map → chunk-CLM7E4I6.js.map} +1 -1
- package/dist/{chunk-OFQ555AX.js → chunk-IDKP6ABU.js} +2 -2
- package/dist/{chunk-36AA7IBJ.js → chunk-L7ISHSG7.js} +53 -20
- package/dist/chunk-L7ISHSG7.js.map +1 -0
- package/dist/{chunk-LBMC4D6D.js → chunk-NVKK7UDN.js} +1 -1
- package/dist/chunk-NVKK7UDN.js.map +1 -0
- package/dist/chunk-X3JRXEIB.js +98 -0
- package/dist/chunk-X3JRXEIB.js.map +1 -0
- package/dist/client.cjs +29 -12
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -2
- package/dist/client.d.ts +3 -2
- package/dist/client.js +2 -2
- package/dist/{table-CIH7jZ2h.d.ts → columns-0lbT9stl.d.ts} +157 -138
- package/dist/{table-DihEAlxG.d.cts → columns-Bxv7Oo9o.d.cts} +157 -138
- package/dist/dynamodb/index.d.cts +3 -2
- package/dist/dynamodb/index.d.ts +3 -2
- package/dist/encryption/index.cjs +54 -16
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +807 -6
- package/dist/encryption/index.d.ts +807 -6
- package/dist/encryption/index.js +6 -6
- package/dist/encryption/v3.cjs +1078 -973
- package/dist/encryption/v3.cjs.map +1 -1
- package/dist/encryption/v3.d.cts +15 -12
- package/dist/encryption/v3.d.ts +15 -12
- package/dist/encryption/v3.js +50 -22
- package/dist/encryption/v3.js.map +1 -1
- package/dist/eql/v3/index.cjs +130 -79
- package/dist/eql/v3/index.cjs.map +1 -1
- package/dist/eql/v3/index.d.cts +115 -13
- package/dist/eql/v3/index.d.ts +115 -13
- package/dist/eql/v3/index.js +16 -6
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +5 -5
- package/dist/errors/index.d.ts +5 -5
- package/dist/errors/index.js +1 -1
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.js +2 -2
- package/dist/index-BquA71_Y.d.ts +24 -0
- package/dist/index-fhWTOV0K.d.cts +24 -0
- package/dist/index.cjs +79 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -17
- package/dist/index.d.ts +5 -17
- package/dist/index.js +6 -6
- package/dist/schema/index.cjs +29 -12
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +2 -2
- package/dist/{types-public-CpS5KjwX.d.ts → types-public-QMjYNfQO.d.cts} +765 -726
- package/dist/{types-public-CpS5KjwX.d.cts → types-public-QMjYNfQO.d.ts} +765 -726
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/dist/types-public.js +1 -1
- package/dist/wasm-inline.d.ts +779 -405
- package/dist/wasm-inline.js +606 -299
- package/dist/wasm-inline.js.map +1 -1
- package/package.json +25 -53
- package/dist/chunk-36AA7IBJ.js.map +0 -1
- package/dist/chunk-4AVL4VZD.js.map +0 -1
- package/dist/chunk-IADZCZEA.js +0 -23
- package/dist/chunk-IADZCZEA.js.map +0 -1
- package/dist/chunk-IBSK6P33.js +0 -209
- package/dist/chunk-IBSK6P33.js.map +0 -1
- package/dist/chunk-LBMC4D6D.js.map +0 -1
- package/dist/chunk-U66S7VIF.js.map +0 -1
- package/dist/client-DSGHBN-g.d.cts +0 -834
- package/dist/client-DfCrlHXh.d.ts +0 -834
- package/dist/drizzle/index.cjs +0 -5617
- package/dist/drizzle/index.cjs.map +0 -1
- package/dist/drizzle/index.d.cts +0 -358
- package/dist/drizzle/index.d.ts +0 -358
- package/dist/drizzle/index.js +0 -1220
- package/dist/drizzle/index.js.map +0 -1
- package/dist/supabase/index.cjs +0 -5951
- package/dist/supabase/index.cjs.map +0 -1
- package/dist/supabase/index.d.cts +0 -223
- package/dist/supabase/index.d.ts +0 -223
- package/dist/supabase/index.js +0 -1217
- package/dist/supabase/index.js.map +0 -1
- /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
|
-
*
|
|
5
|
+
* Allowed cast types for CipherStash schema fields.
|
|
34
6
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
7
|
+
* **Possible values:**
|
|
8
|
+
* - `"bigint"`
|
|
9
|
+
* - `"boolean"`
|
|
10
|
+
* - `"date"`
|
|
11
|
+
* - `"timestamp"`
|
|
12
|
+
* - `"number"`
|
|
13
|
+
* - `"string"`
|
|
14
|
+
* - `"json"`
|
|
15
|
+
* - `"text"`
|
|
40
16
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
197
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
29
|
+
* SDK-facing data types — developer-friendly aliases accepted by `dataType()`.
|
|
215
30
|
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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" | "
|
|
329
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
|
|
657
330
|
indexes: {
|
|
658
|
-
|
|
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" | "
|
|
363
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
|
|
689
364
|
indexes?: {
|
|
690
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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" | "
|
|
573
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
|
|
889
574
|
indexes: {
|
|
890
|
-
|
|
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" | "
|
|
607
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
|
|
921
608
|
indexes?: {
|
|
922
|
-
|
|
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" | "
|
|
644
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json";
|
|
956
645
|
indexes: {
|
|
957
|
-
|
|
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" | "
|
|
681
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "text" | "timestamp" | "json" | undefined;
|
|
991
682
|
indexes?: {
|
|
992
|
-
|
|
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
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
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
|
-
|
|
1134
|
+
accessKey?: string;
|
|
1107
1135
|
/**
|
|
1108
|
-
*
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
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
|
-
|
|
1140
|
+
clientId?: string;
|
|
1125
1141
|
/**
|
|
1126
|
-
*
|
|
1127
|
-
*
|
|
1128
|
-
*
|
|
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
|
-
|
|
1146
|
+
clientKey?: string;
|
|
1145
1147
|
/**
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
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
|
-
* @
|
|
1152
|
-
|
|
1153
|
-
|
|
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
|
-
*
|
|
1156
|
-
*
|
|
1157
|
-
*
|
|
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
|
-
*
|
|
1160
|
-
*
|
|
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
|
-
*
|
|
1164
|
-
*
|
|
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
|
-
|
|
1181
|
+
authStrategy?: AuthStrategy;
|
|
1174
1182
|
/**
|
|
1175
|
-
*
|
|
1176
|
-
*
|
|
1177
|
-
*
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
1188
|
-
*
|
|
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
|
-
*
|
|
1192
|
-
*
|
|
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
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
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
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
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
|
-
*
|
|
1220
|
-
*
|
|
1221
|
-
*
|
|
1222
|
-
* the
|
|
1223
|
-
*
|
|
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
|
-
*
|
|
1234
|
-
*
|
|
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
|
-
|
|
1256
|
+
buildColumnKeyMap?(): Record<string, string>;
|
|
1238
1257
|
}
|
|
1258
|
+
type EncryptionClientConfig = {
|
|
1259
|
+
schemas: AtLeastOneCsTable<BuildableTable>;
|
|
1260
|
+
config?: ClientConfig;
|
|
1261
|
+
};
|
|
1239
1262
|
/**
|
|
1240
|
-
*
|
|
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
|
-
*
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
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
|
-
*
|
|
1250
|
-
*
|
|
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
|
|
1254
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1266
|
-
*
|
|
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
|
|
1270
|
-
[K in keyof
|
|
1271
|
-
}
|
|
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
|
-
*
|
|
1274
|
-
*
|
|
1275
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
1331
|
+
* Maps a plaintext model type to its encrypted form using the table schema.
|
|
1309
1332
|
*
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
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
|
-
*
|
|
1316
|
-
*
|
|
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
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
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
|
-
|
|
1382
|
+
type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>;
|
|
1351
1383
|
/**
|
|
1352
|
-
*
|
|
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
|
-
*
|
|
1370
|
-
*
|
|
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
|
-
|
|
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 {
|
|
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 };
|