@cipherstash/stack 0.19.0 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +531 -0
  2. package/README.md +95 -77
  3. package/dist/adapter-kit.cjs +923 -0
  4. package/dist/adapter-kit.cjs.map +1 -0
  5. package/dist/adapter-kit.d.cts +82 -0
  6. package/dist/adapter-kit.d.ts +82 -0
  7. package/dist/adapter-kit.js +47 -0
  8. package/dist/adapter-kit.js.map +1 -0
  9. package/dist/base-operation-AOAIvsSB.d.cts +32 -0
  10. package/dist/base-operation-FXEzUXIq.d.ts +32 -0
  11. package/dist/{chunk-4AVL4VZD.js → chunk-3B5ZX3IS.js} +3 -1
  12. package/dist/chunk-3B5ZX3IS.js.map +1 -0
  13. package/dist/chunk-7333ZC6L.js +48 -0
  14. package/dist/chunk-7333ZC6L.js.map +1 -0
  15. package/dist/{chunk-MP3SSDNN.js → chunk-CLM7E4I6.js} +15 -15
  16. package/dist/{chunk-MP3SSDNN.js.map → chunk-CLM7E4I6.js.map} +1 -1
  17. package/dist/{chunk-U66S7VIF.js → chunk-V2Q3NYIH.js} +166 -107
  18. package/dist/chunk-V2Q3NYIH.js.map +1 -0
  19. package/dist/chunk-X3JRXEIB.js +98 -0
  20. package/dist/chunk-X3JRXEIB.js.map +1 -0
  21. package/dist/{chunk-36AA7IBJ.js → chunk-ZTP5QJ27.js} +51 -18
  22. package/dist/chunk-ZTP5QJ27.js.map +1 -0
  23. package/dist/client.cjs +29 -12
  24. package/dist/client.cjs.map +1 -1
  25. package/dist/client.d.cts +3 -2
  26. package/dist/client.d.ts +3 -2
  27. package/dist/client.js +2 -2
  28. package/dist/{table-DihEAlxG.d.cts → columns-D2_YzrCX.d.cts} +155 -136
  29. package/dist/{table-CIH7jZ2h.d.ts → columns-rZc7fQHI.d.ts} +155 -136
  30. package/dist/dynamodb/index.d.cts +3 -2
  31. package/dist/dynamodb/index.d.ts +3 -2
  32. package/dist/encryption/index.cjs +54 -16
  33. package/dist/encryption/index.cjs.map +1 -1
  34. package/dist/encryption/index.d.cts +807 -6
  35. package/dist/encryption/index.d.ts +807 -6
  36. package/dist/encryption/index.js +4 -4
  37. package/dist/encryption/v3.cjs +1078 -973
  38. package/dist/encryption/v3.cjs.map +1 -1
  39. package/dist/encryption/v3.d.cts +15 -12
  40. package/dist/encryption/v3.d.ts +15 -12
  41. package/dist/encryption/v3.js +49 -21
  42. package/dist/encryption/v3.js.map +1 -1
  43. package/dist/eql/v3/index.cjs +130 -79
  44. package/dist/eql/v3/index.cjs.map +1 -1
  45. package/dist/eql/v3/index.d.cts +115 -13
  46. package/dist/eql/v3/index.d.ts +115 -13
  47. package/dist/eql/v3/index.js +16 -6
  48. package/dist/index-BquA71_Y.d.ts +24 -0
  49. package/dist/index-fhWTOV0K.d.cts +24 -0
  50. package/dist/index.cjs +79 -27
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +5 -17
  53. package/dist/index.d.ts +5 -17
  54. package/dist/index.js +4 -4
  55. package/dist/schema/index.cjs +29 -12
  56. package/dist/schema/index.cjs.map +1 -1
  57. package/dist/schema/index.d.cts +1 -1
  58. package/dist/schema/index.d.ts +1 -1
  59. package/dist/schema/index.js +2 -2
  60. package/dist/{types-public-CpS5KjwX.d.ts → types-public-QMjYNfQO.d.cts} +765 -726
  61. package/dist/{types-public-CpS5KjwX.d.cts → types-public-QMjYNfQO.d.ts} +765 -726
  62. package/dist/types-public.cjs.map +1 -1
  63. package/dist/types-public.d.cts +1 -1
  64. package/dist/types-public.d.ts +1 -1
  65. package/dist/types-public.js +1 -1
  66. package/dist/wasm-inline.d.ts +779 -405
  67. package/dist/wasm-inline.js +606 -299
  68. package/dist/wasm-inline.js.map +1 -1
  69. package/package.json +25 -53
  70. package/dist/chunk-36AA7IBJ.js.map +0 -1
  71. package/dist/chunk-4AVL4VZD.js.map +0 -1
  72. package/dist/chunk-IADZCZEA.js +0 -23
  73. package/dist/chunk-IADZCZEA.js.map +0 -1
  74. package/dist/chunk-IBSK6P33.js +0 -209
  75. package/dist/chunk-IBSK6P33.js.map +0 -1
  76. package/dist/chunk-U66S7VIF.js.map +0 -1
  77. package/dist/client-DSGHBN-g.d.cts +0 -834
  78. package/dist/client-DfCrlHXh.d.ts +0 -834
  79. package/dist/drizzle/index.cjs +0 -5617
  80. package/dist/drizzle/index.cjs.map +0 -1
  81. package/dist/drizzle/index.d.cts +0 -358
  82. package/dist/drizzle/index.d.ts +0 -358
  83. package/dist/drizzle/index.js +0 -1220
  84. package/dist/drizzle/index.js.map +0 -1
  85. package/dist/supabase/index.cjs +0 -5951
  86. package/dist/supabase/index.cjs.map +0 -1
  87. package/dist/supabase/index.d.cts +0 -223
  88. package/dist/supabase/index.d.ts +0 -223
  89. package/dist/supabase/index.js +0 -1217
  90. package/dist/supabase/index.js.map +0 -1
@@ -15,6 +15,551 @@ import {
15
15
  newClient as wasmNewClient
16
16
  } from "@cipherstash/protect-ffi/wasm-inline";
17
17
 
18
+ // src/schema/match-defaults.ts
19
+ function defaultMatchOpts() {
20
+ return {
21
+ tokenizer: { kind: "ngram", token_length: 3 },
22
+ token_filters: [{ kind: "downcase" }],
23
+ k: 6,
24
+ m: 2048,
25
+ include_original: true
26
+ };
27
+ }
28
+
29
+ // src/eql/v3/columns.ts
30
+ var STORAGE_ONLY = {
31
+ equality: false,
32
+ orderAndRange: false,
33
+ freeTextSearch: false
34
+ };
35
+ var EQUALITY_ONLY = {
36
+ equality: true,
37
+ orderAndRange: false,
38
+ freeTextSearch: false
39
+ };
40
+ var ORDER_AND_RANGE = {
41
+ equality: true,
42
+ orderAndRange: true,
43
+ freeTextSearch: false
44
+ };
45
+ var MATCH_ONLY = {
46
+ equality: false,
47
+ orderAndRange: false,
48
+ freeTextSearch: true
49
+ };
50
+ var TEXT_SEARCH = {
51
+ equality: true,
52
+ orderAndRange: true,
53
+ freeTextSearch: true
54
+ };
55
+ var TEXT_SEARCH_EQL_TYPE = "public.eql_v3_text_search";
56
+ var INTEGER = {
57
+ eqlType: "public.eql_v3_integer",
58
+ castAs: "number",
59
+ capabilities: STORAGE_ONLY
60
+ };
61
+ var INTEGER_EQ = {
62
+ eqlType: "public.eql_v3_integer_eq",
63
+ castAs: "number",
64
+ capabilities: EQUALITY_ONLY
65
+ };
66
+ var INTEGER_ORD_ORE = {
67
+ eqlType: "public.eql_v3_integer_ord_ore",
68
+ castAs: "number",
69
+ capabilities: ORDER_AND_RANGE
70
+ };
71
+ var INTEGER_ORD = {
72
+ eqlType: "public.eql_v3_integer_ord",
73
+ castAs: "number",
74
+ capabilities: ORDER_AND_RANGE
75
+ };
76
+ var SMALLINT = {
77
+ eqlType: "public.eql_v3_smallint",
78
+ castAs: "number",
79
+ capabilities: STORAGE_ONLY
80
+ };
81
+ var SMALLINT_EQ = {
82
+ eqlType: "public.eql_v3_smallint_eq",
83
+ castAs: "number",
84
+ capabilities: EQUALITY_ONLY
85
+ };
86
+ var SMALLINT_ORD_ORE = {
87
+ eqlType: "public.eql_v3_smallint_ord_ore",
88
+ castAs: "number",
89
+ capabilities: ORDER_AND_RANGE
90
+ };
91
+ var SMALLINT_ORD = {
92
+ eqlType: "public.eql_v3_smallint_ord",
93
+ castAs: "number",
94
+ capabilities: ORDER_AND_RANGE
95
+ };
96
+ var BIGINT = {
97
+ eqlType: "public.eql_v3_bigint",
98
+ castAs: "bigint",
99
+ capabilities: STORAGE_ONLY
100
+ };
101
+ var BIGINT_EQ = {
102
+ eqlType: "public.eql_v3_bigint_eq",
103
+ castAs: "bigint",
104
+ capabilities: EQUALITY_ONLY
105
+ };
106
+ var BIGINT_ORD_ORE = {
107
+ eqlType: "public.eql_v3_bigint_ord_ore",
108
+ castAs: "bigint",
109
+ capabilities: ORDER_AND_RANGE
110
+ };
111
+ var BIGINT_ORD = {
112
+ eqlType: "public.eql_v3_bigint_ord",
113
+ castAs: "bigint",
114
+ capabilities: ORDER_AND_RANGE
115
+ };
116
+ var DATE = {
117
+ eqlType: "public.eql_v3_date",
118
+ castAs: "date",
119
+ capabilities: STORAGE_ONLY
120
+ };
121
+ var DATE_EQ = {
122
+ eqlType: "public.eql_v3_date_eq",
123
+ castAs: "date",
124
+ capabilities: EQUALITY_ONLY
125
+ };
126
+ var DATE_ORD_ORE = {
127
+ eqlType: "public.eql_v3_date_ord_ore",
128
+ castAs: "date",
129
+ capabilities: ORDER_AND_RANGE
130
+ };
131
+ var DATE_ORD = {
132
+ eqlType: "public.eql_v3_date_ord",
133
+ castAs: "date",
134
+ capabilities: ORDER_AND_RANGE
135
+ };
136
+ var TIMESTAMP = {
137
+ eqlType: "public.eql_v3_timestamp",
138
+ castAs: "timestamp",
139
+ capabilities: STORAGE_ONLY
140
+ };
141
+ var TIMESTAMP_EQ = {
142
+ eqlType: "public.eql_v3_timestamp_eq",
143
+ castAs: "timestamp",
144
+ capabilities: EQUALITY_ONLY
145
+ };
146
+ var TIMESTAMP_ORD_ORE = {
147
+ eqlType: "public.eql_v3_timestamp_ord_ore",
148
+ castAs: "timestamp",
149
+ capabilities: ORDER_AND_RANGE
150
+ };
151
+ var TIMESTAMP_ORD = {
152
+ eqlType: "public.eql_v3_timestamp_ord",
153
+ castAs: "timestamp",
154
+ capabilities: ORDER_AND_RANGE
155
+ };
156
+ var NUMERIC = {
157
+ eqlType: "public.eql_v3_numeric",
158
+ castAs: "number",
159
+ capabilities: STORAGE_ONLY
160
+ };
161
+ var NUMERIC_EQ = {
162
+ eqlType: "public.eql_v3_numeric_eq",
163
+ castAs: "number",
164
+ capabilities: EQUALITY_ONLY
165
+ };
166
+ var NUMERIC_ORD_ORE = {
167
+ eqlType: "public.eql_v3_numeric_ord_ore",
168
+ castAs: "number",
169
+ capabilities: ORDER_AND_RANGE
170
+ };
171
+ var NUMERIC_ORD = {
172
+ eqlType: "public.eql_v3_numeric_ord",
173
+ castAs: "number",
174
+ capabilities: ORDER_AND_RANGE
175
+ };
176
+ var TEXT = {
177
+ eqlType: "public.eql_v3_text",
178
+ castAs: "string",
179
+ capabilities: STORAGE_ONLY
180
+ };
181
+ var TEXT_EQ = {
182
+ eqlType: "public.eql_v3_text_eq",
183
+ castAs: "string",
184
+ capabilities: EQUALITY_ONLY
185
+ };
186
+ var TEXT_MATCH = {
187
+ eqlType: "public.eql_v3_text_match",
188
+ castAs: "string",
189
+ capabilities: MATCH_ONLY
190
+ };
191
+ var TEXT_ORD_ORE = {
192
+ eqlType: "public.eql_v3_text_ord_ore",
193
+ castAs: "string",
194
+ capabilities: ORDER_AND_RANGE
195
+ };
196
+ var TEXT_ORD = {
197
+ eqlType: "public.eql_v3_text_ord",
198
+ castAs: "string",
199
+ capabilities: ORDER_AND_RANGE
200
+ };
201
+ var BOOLEAN = {
202
+ eqlType: "public.eql_v3_boolean",
203
+ castAs: "boolean",
204
+ capabilities: STORAGE_ONLY
205
+ };
206
+ var REAL = {
207
+ eqlType: "public.eql_v3_real",
208
+ castAs: "number",
209
+ capabilities: STORAGE_ONLY
210
+ };
211
+ var REAL_EQ = {
212
+ eqlType: "public.eql_v3_real_eq",
213
+ castAs: "number",
214
+ capabilities: EQUALITY_ONLY
215
+ };
216
+ var REAL_ORD_ORE = {
217
+ eqlType: "public.eql_v3_real_ord_ore",
218
+ castAs: "number",
219
+ capabilities: ORDER_AND_RANGE
220
+ };
221
+ var REAL_ORD = {
222
+ eqlType: "public.eql_v3_real_ord",
223
+ castAs: "number",
224
+ capabilities: ORDER_AND_RANGE
225
+ };
226
+ var DOUBLE = {
227
+ eqlType: "public.eql_v3_double",
228
+ castAs: "number",
229
+ capabilities: STORAGE_ONLY
230
+ };
231
+ var DOUBLE_EQ = {
232
+ eqlType: "public.eql_v3_double_eq",
233
+ castAs: "number",
234
+ capabilities: EQUALITY_ONLY
235
+ };
236
+ var DOUBLE_ORD_ORE = {
237
+ eqlType: "public.eql_v3_double_ord_ore",
238
+ castAs: "number",
239
+ capabilities: ORDER_AND_RANGE
240
+ };
241
+ var DOUBLE_ORD = {
242
+ eqlType: "public.eql_v3_double_ord",
243
+ castAs: "number",
244
+ capabilities: ORDER_AND_RANGE
245
+ };
246
+ function indexesForCapabilities(capabilities, castAs, ordering) {
247
+ const indexes = {};
248
+ if (capabilities.equality && (!capabilities.orderAndRange || castAs === "string")) {
249
+ indexes.unique = { token_filters: [] };
250
+ }
251
+ if (capabilities.orderAndRange) {
252
+ indexes[ordering] = {};
253
+ }
254
+ if (capabilities.freeTextSearch) {
255
+ indexes.match = { ...defaultMatchOpts(), include_original: false };
256
+ }
257
+ if (capabilities.searchableJson) {
258
+ indexes.ste_vec = {
259
+ prefix: "enabled",
260
+ array_index_mode: { item: true, wildcard: true, position: false },
261
+ mode: "compat"
262
+ };
263
+ }
264
+ return indexes;
265
+ }
266
+ function orderingForEqlType(eqlType) {
267
+ return eqlType.endsWith("_ord_ore") ? "ore" : "ope";
268
+ }
269
+ function isQueryableCapabilities(capabilities) {
270
+ return capabilities.equality || capabilities.orderAndRange || capabilities.freeTextSearch || (capabilities.searchableJson ?? false);
271
+ }
272
+ var EncryptedV3Column = class {
273
+ constructor(columnName, definition) {
274
+ this.columnName = columnName;
275
+ this.definition = definition;
276
+ }
277
+ columnName;
278
+ definition;
279
+ getName() {
280
+ return this.columnName;
281
+ }
282
+ /** The concrete EQL v3 domain name. Metadata only; not emitted by `build()`. */
283
+ getEqlType() {
284
+ return this.definition.eqlType;
285
+ }
286
+ /** The semantic query capabilities this domain exposes. Metadata only. */
287
+ getQueryCapabilities() {
288
+ return this.definition.capabilities;
289
+ }
290
+ /** `true` when this domain can produce at least one kind of query term. */
291
+ isQueryable() {
292
+ return isQueryableCapabilities(
293
+ this.definition.capabilities
294
+ );
295
+ }
296
+ /** Emit the encrypt-config column: `cast_as` plus capability-derived indexes. */
297
+ build() {
298
+ return {
299
+ cast_as: this.definition.castAs,
300
+ indexes: indexesForCapabilities(
301
+ this.definition.capabilities,
302
+ this.definition.castAs,
303
+ orderingForEqlType(this.definition.eqlType)
304
+ )
305
+ };
306
+ }
307
+ };
308
+ var TEXT_SEARCH_DOMAIN = {
309
+ eqlType: TEXT_SEARCH_EQL_TYPE,
310
+ castAs: "string",
311
+ capabilities: TEXT_SEARCH
312
+ };
313
+ var EncryptedTextSearchColumn = class extends EncryptedV3Column {
314
+ constructor(columnName) {
315
+ super(columnName, TEXT_SEARCH_DOMAIN);
316
+ }
317
+ };
318
+ var EncryptedIntegerColumn = class extends EncryptedV3Column {
319
+ };
320
+ var EncryptedIntegerEqColumn = class extends EncryptedV3Column {
321
+ };
322
+ var EncryptedIntegerOrdOreColumn = class extends EncryptedV3Column {
323
+ };
324
+ var EncryptedIntegerOrdColumn = class extends EncryptedV3Column {
325
+ };
326
+ var EncryptedSmallintColumn = class extends EncryptedV3Column {
327
+ };
328
+ var EncryptedSmallintEqColumn = class extends EncryptedV3Column {
329
+ };
330
+ var EncryptedSmallintOrdOreColumn = class extends EncryptedV3Column {
331
+ };
332
+ var EncryptedSmallintOrdColumn = class extends EncryptedV3Column {
333
+ };
334
+ var EncryptedBigintColumn = class extends EncryptedV3Column {
335
+ };
336
+ var EncryptedBigintEqColumn = class extends EncryptedV3Column {
337
+ };
338
+ var EncryptedBigintOrdOreColumn = class extends EncryptedV3Column {
339
+ };
340
+ var EncryptedBigintOrdColumn = class extends EncryptedV3Column {
341
+ };
342
+ var EncryptedDateColumn = class extends EncryptedV3Column {
343
+ };
344
+ var EncryptedDateEqColumn = class extends EncryptedV3Column {
345
+ };
346
+ var EncryptedDateOrdOreColumn = class extends EncryptedV3Column {
347
+ };
348
+ var EncryptedDateOrdColumn = class extends EncryptedV3Column {
349
+ };
350
+ var EncryptedTimestampColumn = class extends EncryptedV3Column {
351
+ };
352
+ var EncryptedTimestampEqColumn = class extends EncryptedV3Column {
353
+ };
354
+ var EncryptedTimestampOrdOreColumn = class extends EncryptedV3Column {
355
+ };
356
+ var EncryptedTimestampOrdColumn = class extends EncryptedV3Column {
357
+ };
358
+ var EncryptedNumericColumn = class extends EncryptedV3Column {
359
+ };
360
+ var EncryptedNumericEqColumn = class extends EncryptedV3Column {
361
+ };
362
+ var EncryptedNumericOrdOreColumn = class extends EncryptedV3Column {
363
+ };
364
+ var EncryptedNumericOrdColumn = class extends EncryptedV3Column {
365
+ };
366
+ var EncryptedTextColumn = class extends EncryptedV3Column {
367
+ };
368
+ var EncryptedTextEqColumn = class extends EncryptedV3Column {
369
+ };
370
+ var EncryptedTextMatchColumn = class extends EncryptedV3Column {
371
+ };
372
+ var EncryptedTextOrdOreColumn = class extends EncryptedV3Column {
373
+ };
374
+ var EncryptedTextOrdColumn = class extends EncryptedV3Column {
375
+ };
376
+ var EncryptedBooleanColumn = class extends EncryptedV3Column {
377
+ };
378
+ var EncryptedRealColumn = class extends EncryptedV3Column {
379
+ };
380
+ var EncryptedRealEqColumn = class extends EncryptedV3Column {
381
+ };
382
+ var EncryptedRealOrdOreColumn = class extends EncryptedV3Column {
383
+ };
384
+ var EncryptedRealOrdColumn = class extends EncryptedV3Column {
385
+ };
386
+ var EncryptedDoubleColumn = class extends EncryptedV3Column {
387
+ };
388
+ var EncryptedDoubleEqColumn = class extends EncryptedV3Column {
389
+ };
390
+ var EncryptedDoubleOrdOreColumn = class extends EncryptedV3Column {
391
+ };
392
+ var EncryptedDoubleOrdColumn = class extends EncryptedV3Column {
393
+ };
394
+ var JSON_DOMAIN = {
395
+ eqlType: "public.eql_v3_json",
396
+ castAs: "json",
397
+ capabilities: {
398
+ equality: false,
399
+ orderAndRange: false,
400
+ freeTextSearch: false,
401
+ searchableJson: true
402
+ }
403
+ };
404
+ var EncryptedJsonColumn = class extends EncryptedV3Column {
405
+ constructor(columnName) {
406
+ super(columnName, JSON_DOMAIN);
407
+ }
408
+ };
409
+
410
+ // src/eql/v3/table.ts
411
+ var EncryptedTable = class {
412
+ constructor(tableName, columnBuilders) {
413
+ this.tableName = tableName;
414
+ this.columnBuilders = columnBuilders;
415
+ }
416
+ tableName;
417
+ columnBuilders;
418
+ build() {
419
+ const builtColumns = /* @__PURE__ */ Object.create(null);
420
+ for (const builder of Object.values(this.columnBuilders)) {
421
+ const name = builder.getName();
422
+ if (Object.hasOwn(builtColumns, name)) {
423
+ throw new Error(
424
+ `[eql/v3]: duplicate column name "${name}" in table "${this.tableName}" \u2014 two columns resolve to the same DB name`
425
+ );
426
+ }
427
+ builtColumns[name] = builder.build();
428
+ }
429
+ return {
430
+ tableName: this.tableName,
431
+ columns: builtColumns
432
+ };
433
+ }
434
+ /**
435
+ * Map each column's JS property name to its DB column name (`getName()`).
436
+ * The model path matches user models by property name but must address the
437
+ * encrypt config and FFI by DB name — `build()` keys columns by DB name, so
438
+ * the two only agree when property == name. This recovers the mapping that
439
+ * `build()` discards.
440
+ *
441
+ * NULL PROTOTYPE — load-bearing. Callers index this map by a column name that
442
+ * ultimately comes from the database (`addJsonbCastsV3`, `filterColumnName`,
443
+ * the mutation transform). On a plain object literal, a column named
444
+ * `constructor` / `toString` / `valueOf` / `__proto__` resolves to an
445
+ * inherited `Object.prototype` member, which is truthy — so a *plaintext*
446
+ * column with such a name would be mistaken for a mapped encrypted column and
447
+ * its `Object.prototype` value interpolated into the emitted select string.
448
+ * `encryptedTable()` rejects such names as JS *properties*, but nothing
449
+ * constrains the DB column names a table may contain.
450
+ */
451
+ buildColumnKeyMap() {
452
+ const map = /* @__PURE__ */ Object.create(null);
453
+ for (const [property, builder] of Object.entries(this.columnBuilders)) {
454
+ map[property] = builder.getName();
455
+ }
456
+ return map;
457
+ }
458
+ };
459
+ var RESERVED_TABLE_KEYS = /* @__PURE__ */ new Set([
460
+ "tableName",
461
+ "columnBuilders",
462
+ "_columnType",
463
+ "build",
464
+ "buildColumnKeyMap"
465
+ ]);
466
+ function isReservedTableKey(tableBuilder, colName) {
467
+ return RESERVED_TABLE_KEYS.has(colName) || colName in tableBuilder;
468
+ }
469
+ function encryptedTable(tableName, columns) {
470
+ const tableBuilder = new EncryptedTable(
471
+ tableName,
472
+ columns
473
+ );
474
+ for (const [colName, colBuilder] of Object.entries(columns)) {
475
+ if (isReservedTableKey(tableBuilder, colName)) {
476
+ throw new Error(
477
+ `Column name "${colName}" collides with a reserved EncryptedTable property`
478
+ );
479
+ }
480
+ ;
481
+ tableBuilder[colName] = colBuilder;
482
+ }
483
+ return tableBuilder;
484
+ }
485
+ function buildEncryptConfig(...tables) {
486
+ const config = {
487
+ v: 1,
488
+ tables: {}
489
+ };
490
+ for (const tb of tables) {
491
+ const tableDef = tb.build();
492
+ if (Object.hasOwn(config.tables, tableDef.tableName)) {
493
+ throw new Error(
494
+ `[eql/v3]: duplicate table name "${tableDef.tableName}" passed to buildEncryptConfig \u2014 each table must have a unique name`
495
+ );
496
+ }
497
+ config.tables[tableDef.tableName] = tableDef.columns;
498
+ }
499
+ return config;
500
+ }
501
+
502
+ // src/eql/v3/types.ts
503
+ var types = {
504
+ // integer
505
+ Integer: (name) => new EncryptedIntegerColumn(name, INTEGER),
506
+ IntegerEq: (name) => new EncryptedIntegerEqColumn(name, INTEGER_EQ),
507
+ IntegerOrdOre: (name) => new EncryptedIntegerOrdOreColumn(name, INTEGER_ORD_ORE),
508
+ IntegerOrd: (name) => new EncryptedIntegerOrdColumn(name, INTEGER_ORD),
509
+ // smallint
510
+ Smallint: (name) => new EncryptedSmallintColumn(name, SMALLINT),
511
+ SmallintEq: (name) => new EncryptedSmallintEqColumn(name, SMALLINT_EQ),
512
+ SmallintOrdOre: (name) => new EncryptedSmallintOrdOreColumn(name, SMALLINT_ORD_ORE),
513
+ SmallintOrd: (name) => new EncryptedSmallintOrdColumn(name, SMALLINT_ORD),
514
+ // bigint (int8) — plaintext is a JS `bigint`, round-tripped losslessly by
515
+ // the native protect-ffi boundary (see ./columns)
516
+ Bigint: (name) => new EncryptedBigintColumn(name, BIGINT),
517
+ BigintEq: (name) => new EncryptedBigintEqColumn(name, BIGINT_EQ),
518
+ BigintOrdOre: (name) => new EncryptedBigintOrdOreColumn(name, BIGINT_ORD_ORE),
519
+ BigintOrd: (name) => new EncryptedBigintOrdColumn(name, BIGINT_ORD),
520
+ // date
521
+ Date: (name) => new EncryptedDateColumn(name, DATE),
522
+ DateEq: (name) => new EncryptedDateEqColumn(name, DATE_EQ),
523
+ DateOrdOre: (name) => new EncryptedDateOrdOreColumn(name, DATE_ORD_ORE),
524
+ DateOrd: (name) => new EncryptedDateOrdColumn(name, DATE_ORD),
525
+ // timestamp
526
+ Timestamp: (name) => new EncryptedTimestampColumn(name, TIMESTAMP),
527
+ TimestampEq: (name) => new EncryptedTimestampEqColumn(name, TIMESTAMP_EQ),
528
+ TimestampOrdOre: (name) => new EncryptedTimestampOrdOreColumn(name, TIMESTAMP_ORD_ORE),
529
+ TimestampOrd: (name) => new EncryptedTimestampOrdColumn(name, TIMESTAMP_ORD),
530
+ // numeric
531
+ Numeric: (name) => new EncryptedNumericColumn(name, NUMERIC),
532
+ NumericEq: (name) => new EncryptedNumericEqColumn(name, NUMERIC_EQ),
533
+ NumericOrdOre: (name) => new EncryptedNumericOrdOreColumn(name, NUMERIC_ORD_ORE),
534
+ NumericOrd: (name) => new EncryptedNumericOrdColumn(name, NUMERIC_ORD),
535
+ // text
536
+ Text: (name) => new EncryptedTextColumn(name, TEXT),
537
+ TextEq: (name) => new EncryptedTextEqColumn(name, TEXT_EQ),
538
+ TextMatch: (name) => new EncryptedTextMatchColumn(name, TEXT_MATCH),
539
+ TextOrdOre: (name) => new EncryptedTextOrdOreColumn(name, TEXT_ORD_ORE),
540
+ TextOrd: (name) => new EncryptedTextOrdColumn(name, TEXT_ORD),
541
+ TextSearch: (name) => new EncryptedTextSearchColumn(name),
542
+ // boolean
543
+ Boolean: (name) => new EncryptedBooleanColumn(name, BOOLEAN),
544
+ // real
545
+ Real: (name) => new EncryptedRealColumn(name, REAL),
546
+ RealEq: (name) => new EncryptedRealEqColumn(name, REAL_EQ),
547
+ RealOrdOre: (name) => new EncryptedRealOrdOreColumn(name, REAL_ORD_ORE),
548
+ RealOrd: (name) => new EncryptedRealOrdColumn(name, REAL_ORD),
549
+ // double
550
+ Double: (name) => new EncryptedDoubleColumn(name, DOUBLE),
551
+ DoubleEq: (name) => new EncryptedDoubleEqColumn(name, DOUBLE_EQ),
552
+ DoubleOrdOre: (name) => new EncryptedDoubleOrdOreColumn(name, DOUBLE_ORD_ORE),
553
+ DoubleOrd: (name) => new EncryptedDoubleOrdColumn(name, DOUBLE_ORD),
554
+ // json (encrypted JSONB document, ste_vec containment)
555
+ Json: (name) => new EncryptedJsonColumn(name)
556
+ // `satisfies` is load-bearing, not decoration: `DOMAIN_REGISTRY` derives itself
557
+ // by calling every value here at module load. A non-factory export would throw
558
+ // during module evaluation and take the supabase introspect/schema-build/verify
559
+ // path down with it. This turns that into a compile error at the offending line.
560
+ // `as const` applies first, so literal key inference is preserved.
561
+ };
562
+
18
563
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
19
564
  var external_exports = {};
20
565
  __export(external_exports, {
@@ -2805,9 +3350,9 @@ var ZodUnion = class extends ZodType {
2805
3350
  return this._def.options;
2806
3351
  }
2807
3352
  };
2808
- ZodUnion.create = (types, params) => {
3353
+ ZodUnion.create = (types2, params) => {
2809
3354
  return new ZodUnion({
2810
- options: types,
3355
+ options: types2,
2811
3356
  typeName: ZodFirstPartyTypeKind.ZodUnion,
2812
3357
  ...processCreateParams(params)
2813
3358
  });
@@ -4056,17 +4601,6 @@ var coerce = {
4056
4601
  };
4057
4602
  var NEVER = INVALID;
4058
4603
 
4059
- // src/schema/match-defaults.ts
4060
- function defaultMatchOpts() {
4061
- return {
4062
- tokenizer: { kind: "ngram", token_length: 3 },
4063
- token_filters: [{ kind: "downcase" }],
4064
- k: 6,
4065
- m: 2048,
4066
- include_original: true
4067
- };
4068
- }
4069
-
4070
4604
  // src/schema/index.ts
4071
4605
  var eqlCastAsEnum = external_exports.enum([
4072
4606
  "text",
@@ -4123,6 +4657,7 @@ var tokenizerSchema = external_exports.union([
4123
4657
  })
4124
4658
  ]).default({ kind: "ngram", token_length: 3 }).optional();
4125
4659
  var oreIndexOptsSchema = external_exports.object({});
4660
+ var opeIndexOptsSchema = external_exports.object({});
4126
4661
  var uniqueIndexOptsSchema = external_exports.object({
4127
4662
  token_filters: external_exports.array(tokenFilterSchema).default([]).optional()
4128
4663
  });
@@ -4144,10 +4679,12 @@ var arrayIndexModeSchema = external_exports.union([
4144
4679
  ]);
4145
4680
  var steVecIndexOptsSchema = external_exports.object({
4146
4681
  prefix: external_exports.string(),
4147
- array_index_mode: arrayIndexModeSchema.optional()
4682
+ array_index_mode: arrayIndexModeSchema.optional(),
4683
+ mode: external_exports.enum(["compat", "standard"]).optional()
4148
4684
  });
4149
4685
  var indexesSchema = external_exports.object({
4150
4686
  ore: oreIndexOptsSchema.optional(),
4687
+ ope: opeIndexOptsSchema.optional(),
4151
4688
  unique: uniqueIndexOptsSchema.optional(),
4152
4689
  match: matchIndexOptsSchema.optional(),
4153
4690
  ste_vec: steVecIndexOptsSchema.optional()
@@ -4162,287 +4699,6 @@ var encryptConfigSchema = external_exports.object({
4162
4699
  v: external_exports.number(),
4163
4700
  tables: tablesSchema
4164
4701
  });
4165
- var EncryptedField = class {
4166
- valueName;
4167
- castAsValue;
4168
- constructor(valueName) {
4169
- this.valueName = valueName;
4170
- this.castAsValue = "string";
4171
- }
4172
- /**
4173
- * Set or override the plaintext data type for this field.
4174
- *
4175
- * By default all values are treated as `'string'`. Use this method to specify
4176
- * a different type so the encryption layer knows how to encode the plaintext
4177
- * before encrypting.
4178
- *
4179
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.
4180
- * @returns This `EncryptedField` instance for method chaining.
4181
- *
4182
- * @example
4183
- * ```typescript
4184
- * import { encryptedField } from "@cipherstash/stack/schema"
4185
- *
4186
- * const age = encryptedField("age").dataType("number")
4187
- * ```
4188
- */
4189
- dataType(castAs) {
4190
- this.castAsValue = castAs;
4191
- return this;
4192
- }
4193
- build() {
4194
- return {
4195
- cast_as: this.castAsValue,
4196
- indexes: {}
4197
- };
4198
- }
4199
- getName() {
4200
- return this.valueName;
4201
- }
4202
- };
4203
- var EncryptedColumn = class {
4204
- columnName;
4205
- castAsValue;
4206
- indexesValue = {};
4207
- constructor(columnName) {
4208
- this.columnName = columnName;
4209
- this.castAsValue = "string";
4210
- }
4211
- /**
4212
- * Set or override the plaintext data type for this column.
4213
- *
4214
- * By default all columns are treated as `'string'`. Use this method to specify
4215
- * a different type so the encryption layer knows how to encode the plaintext
4216
- * before encrypting.
4217
- *
4218
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
4219
- * @returns This `EncryptedColumn` instance for method chaining.
4220
- *
4221
- * @example
4222
- * ```typescript
4223
- * import { encryptedColumn } from "@cipherstash/stack/schema"
4224
- *
4225
- * const dateOfBirth = encryptedColumn("date_of_birth").dataType("date")
4226
- * ```
4227
- */
4228
- dataType(castAs) {
4229
- this.castAsValue = castAs;
4230
- return this;
4231
- }
4232
- /**
4233
- * Enable Order-Revealing Encryption (ORE) indexing on this column.
4234
- *
4235
- * ORE allows sorting, comparison, and range queries on encrypted data.
4236
- * Use with `encryptQuery` and `queryType: 'orderAndRange'`.
4237
- *
4238
- * @returns This `EncryptedColumn` instance for method chaining.
4239
- *
4240
- * @example
4241
- * ```typescript
4242
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
4243
- *
4244
- * const users = encryptedTable("users", {
4245
- * email: encryptedColumn("email").orderAndRange(),
4246
- * })
4247
- * ```
4248
- */
4249
- orderAndRange() {
4250
- this.indexesValue.ore = {};
4251
- return this;
4252
- }
4253
- /**
4254
- * Enable an exact-match (unique) index on this column.
4255
- *
4256
- * Allows equality queries on encrypted data. Use with `encryptQuery`
4257
- * and `queryType: 'equality'`.
4258
- *
4259
- * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).
4260
- * When omitted, no token filters are applied.
4261
- * @returns This `EncryptedColumn` instance for method chaining.
4262
- *
4263
- * @example
4264
- * ```typescript
4265
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
4266
- *
4267
- * const users = encryptedTable("users", {
4268
- * email: encryptedColumn("email").equality(),
4269
- * })
4270
- * ```
4271
- */
4272
- equality(tokenFilters) {
4273
- this.indexesValue.unique = {
4274
- token_filters: tokenFilters ?? []
4275
- };
4276
- return this;
4277
- }
4278
- /**
4279
- * Enable a full-text / fuzzy search (match) index on this column.
4280
- *
4281
- * Uses n-gram tokenization by default for substring and fuzzy matching.
4282
- * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.
4283
- *
4284
- * @param opts - Optional match index configuration. Defaults to 3-character ngram
4285
- * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.
4286
- * @returns This `EncryptedColumn` instance for method chaining.
4287
- *
4288
- * @example
4289
- * ```typescript
4290
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
4291
- *
4292
- * const users = encryptedTable("users", {
4293
- * email: encryptedColumn("email").freeTextSearch(),
4294
- * })
4295
- *
4296
- * // With custom options
4297
- * const posts = encryptedTable("posts", {
4298
- * body: encryptedColumn("body").freeTextSearch({
4299
- * tokenizer: { kind: "ngram", token_length: 4 },
4300
- * k: 8,
4301
- * m: 4096,
4302
- * }),
4303
- * })
4304
- * ```
4305
- */
4306
- freeTextSearch(opts) {
4307
- const defaults = defaultMatchOpts();
4308
- this.indexesValue.match = {
4309
- tokenizer: opts?.tokenizer ?? defaults.tokenizer,
4310
- token_filters: opts?.token_filters ?? defaults.token_filters,
4311
- k: opts?.k ?? defaults.k,
4312
- m: opts?.m ?? defaults.m,
4313
- include_original: opts?.include_original ?? defaults.include_original
4314
- };
4315
- return this;
4316
- }
4317
- /**
4318
- * Configure this column for searchable encrypted JSON (STE-Vec).
4319
- *
4320
- * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and
4321
- * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the
4322
- * data type to `'json'`.
4323
- *
4324
- * When used with `encryptQuery`, the query operation is auto-inferred from
4325
- * the plaintext type: strings become selector queries, objects/arrays become
4326
- * containment queries.
4327
- *
4328
- * @returns This `EncryptedColumn` instance for method chaining.
4329
- *
4330
- * @example
4331
- * ```typescript
4332
- * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
4333
- *
4334
- * const documents = encryptedTable("documents", {
4335
- * metadata: encryptedColumn("metadata").searchableJson(),
4336
- * })
4337
- * ```
4338
- */
4339
- searchableJson() {
4340
- this.castAsValue = "json";
4341
- this.indexesValue.ste_vec = { prefix: "enabled", array_index_mode: "all" };
4342
- return this;
4343
- }
4344
- build() {
4345
- return {
4346
- cast_as: this.castAsValue,
4347
- indexes: this.indexesValue
4348
- };
4349
- }
4350
- getName() {
4351
- return this.columnName;
4352
- }
4353
- };
4354
- var EncryptedTable = class {
4355
- constructor(tableName, columnBuilders) {
4356
- this.tableName = tableName;
4357
- this.columnBuilders = columnBuilders;
4358
- }
4359
- tableName;
4360
- columnBuilders;
4361
- /**
4362
- * Compile this table schema into a `TableDefinition` used internally by the encryption client.
4363
- *
4364
- * Iterates over all column builders, calls `.build()` on each, and assembles
4365
- * the final `{ tableName, columns }` structure. For `searchableJson()` columns,
4366
- * the STE-Vec prefix is automatically set to `"<tableName>/<columnName>"`.
4367
- *
4368
- * @returns A `TableDefinition` containing the table name and built column configs.
4369
- *
4370
- * @example
4371
- * ```typescript
4372
- * const users = encryptedTable("users", {
4373
- * email: encryptedColumn("email").equality(),
4374
- * })
4375
- *
4376
- * const definition = users.build()
4377
- * // { tableName: "users", columns: { email: { cast_as: "string", indexes: { unique: ... } } } }
4378
- * ```
4379
- */
4380
- build() {
4381
- const builtColumns = {};
4382
- const processColumn = (builder, colName) => {
4383
- if (builder instanceof EncryptedColumn) {
4384
- const builtColumn = builder.build();
4385
- if (builtColumn.cast_as === "json" && builtColumn.indexes.ste_vec?.prefix === "enabled") {
4386
- builtColumns[colName] = {
4387
- ...builtColumn,
4388
- indexes: {
4389
- ...builtColumn.indexes,
4390
- ste_vec: {
4391
- ...builtColumn.indexes.ste_vec,
4392
- prefix: `${this.tableName}/${colName}`
4393
- }
4394
- }
4395
- };
4396
- } else {
4397
- builtColumns[colName] = builtColumn;
4398
- }
4399
- } else {
4400
- for (const [key, value] of Object.entries(builder)) {
4401
- if (value instanceof EncryptedField) {
4402
- builtColumns[value.getName()] = value.build();
4403
- } else {
4404
- processColumn(value, key);
4405
- }
4406
- }
4407
- }
4408
- };
4409
- for (const [colName, builder] of Object.entries(this.columnBuilders)) {
4410
- processColumn(builder, colName);
4411
- }
4412
- return {
4413
- tableName: this.tableName,
4414
- columns: builtColumns
4415
- };
4416
- }
4417
- };
4418
- function encryptedTable(tableName, columns) {
4419
- const tableBuilder = new EncryptedTable(
4420
- tableName,
4421
- columns
4422
- );
4423
- for (const [colName, colBuilder] of Object.entries(columns)) {
4424
- ;
4425
- tableBuilder[colName] = colBuilder;
4426
- }
4427
- return tableBuilder;
4428
- }
4429
- function encryptedColumn(columnName) {
4430
- return new EncryptedColumn(columnName);
4431
- }
4432
- function encryptedField(valueName) {
4433
- return new EncryptedField(valueName);
4434
- }
4435
- function buildEncryptConfig(...protectTables) {
4436
- const config = {
4437
- v: 1,
4438
- tables: {}
4439
- };
4440
- for (const tb of protectTables) {
4441
- const tableDef = tb.build();
4442
- config.tables[tableDef.tableName] = tableDef.columns;
4443
- }
4444
- return config;
4445
- }
4446
4702
 
4447
4703
  // src/wasm-inline.ts
4448
4704
  import {
@@ -4500,6 +4756,14 @@ async function Encryption(config) {
4500
4756
  "[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
4501
4757
  );
4502
4758
  }
4759
+ for (const table of schemas) {
4760
+ const isV3 = typeof table.buildColumnKeyMap === "function";
4761
+ if (!isV3) {
4762
+ throw new Error(
4763
+ "[encryption]: `@cipherstash/stack/wasm-inline` is EQL v3 only \u2014 author schemas with `types` / `encryptedTable` from this entry. (EQL v2 is available on the native `@cipherstash/stack` entry.)"
4764
+ );
4765
+ }
4766
+ }
4503
4767
  const encryptConfig = encryptConfigSchema.parse(
4504
4768
  buildEncryptConfig(...schemas)
4505
4769
  );
@@ -4508,7 +4772,8 @@ async function Encryption(config) {
4508
4772
  strategy,
4509
4773
  encryptConfig: normalizeCastAs(encryptConfig),
4510
4774
  clientId: clientConfig.clientId,
4511
- clientKey: clientConfig.clientKey
4775
+ clientKey: clientConfig.clientKey,
4776
+ eqlVersion: 3
4512
4777
  });
4513
4778
  return new WasmEncryptionClient(INTERNAL_CONSTRUCT, client);
4514
4779
  }
@@ -4579,16 +4844,58 @@ function resolveStrategy(cfg) {
4579
4844
  }
4580
4845
  export {
4581
4846
  AccessKeyStrategy2 as AccessKeyStrategy,
4847
+ EncryptedBigintColumn,
4848
+ EncryptedBigintEqColumn,
4849
+ EncryptedBigintOrdColumn,
4850
+ EncryptedBigintOrdOreColumn,
4851
+ EncryptedBooleanColumn,
4852
+ EncryptedDateColumn,
4853
+ EncryptedDateEqColumn,
4854
+ EncryptedDateOrdColumn,
4855
+ EncryptedDateOrdOreColumn,
4856
+ EncryptedDoubleColumn,
4857
+ EncryptedDoubleEqColumn,
4858
+ EncryptedDoubleOrdColumn,
4859
+ EncryptedDoubleOrdOreColumn,
4860
+ EncryptedIntegerColumn,
4861
+ EncryptedIntegerEqColumn,
4862
+ EncryptedIntegerOrdColumn,
4863
+ EncryptedIntegerOrdOreColumn,
4864
+ EncryptedJsonColumn,
4865
+ EncryptedNumericColumn,
4866
+ EncryptedNumericEqColumn,
4867
+ EncryptedNumericOrdColumn,
4868
+ EncryptedNumericOrdOreColumn,
4869
+ EncryptedRealColumn,
4870
+ EncryptedRealEqColumn,
4871
+ EncryptedRealOrdColumn,
4872
+ EncryptedRealOrdOreColumn,
4873
+ EncryptedSmallintColumn,
4874
+ EncryptedSmallintEqColumn,
4875
+ EncryptedSmallintOrdColumn,
4876
+ EncryptedSmallintOrdOreColumn,
4877
+ EncryptedTable,
4878
+ EncryptedTextColumn,
4879
+ EncryptedTextEqColumn,
4880
+ EncryptedTextMatchColumn,
4881
+ EncryptedTextOrdColumn,
4882
+ EncryptedTextOrdOreColumn,
4883
+ EncryptedTextSearchColumn,
4884
+ EncryptedTimestampColumn,
4885
+ EncryptedTimestampEqColumn,
4886
+ EncryptedTimestampOrdColumn,
4887
+ EncryptedTimestampOrdOreColumn,
4582
4888
  Encryption,
4583
4889
  OidcFederationStrategy,
4890
+ TEXT_SEARCH_EQL_TYPE,
4584
4891
  WasmEncryptionClient,
4585
4892
  __resetStrategyDeprecationWarningForTests,
4586
- encryptedColumn,
4587
- encryptedField,
4893
+ buildEncryptConfig,
4588
4894
  encryptedTable,
4589
4895
  getColumnName,
4590
4896
  isEncrypted,
4591
4897
  normalizeCastAs,
4592
- resolveStrategy
4898
+ resolveStrategy,
4899
+ types
4593
4900
  };
4594
4901
  //# sourceMappingURL=wasm-inline.js.map