@cipherstash/stack 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +670 -0
  4. package/dist/bin/stash.js +5049 -0
  5. package/dist/bin/stash.js.map +1 -0
  6. package/dist/chunk-2GZMIJFO.js +2400 -0
  7. package/dist/chunk-2GZMIJFO.js.map +1 -0
  8. package/dist/chunk-5DCT6YU2.js +138 -0
  9. package/dist/chunk-5DCT6YU2.js.map +1 -0
  10. package/dist/chunk-7XRPN2KX.js +336 -0
  11. package/dist/chunk-7XRPN2KX.js.map +1 -0
  12. package/dist/chunk-SJ7JO4ME.js +28 -0
  13. package/dist/chunk-SJ7JO4ME.js.map +1 -0
  14. package/dist/chunk-SUYMGQBY.js +67 -0
  15. package/dist/chunk-SUYMGQBY.js.map +1 -0
  16. package/dist/client-BxJG56Ey.d.cts +647 -0
  17. package/dist/client-DtGq9dJp.d.ts +647 -0
  18. package/dist/client.cjs +347 -0
  19. package/dist/client.cjs.map +1 -0
  20. package/dist/client.d.cts +7 -0
  21. package/dist/client.d.ts +7 -0
  22. package/dist/client.js +11 -0
  23. package/dist/client.js.map +1 -0
  24. package/dist/drizzle/index.cjs +1528 -0
  25. package/dist/drizzle/index.cjs.map +1 -0
  26. package/dist/drizzle/index.d.cts +350 -0
  27. package/dist/drizzle/index.d.ts +350 -0
  28. package/dist/drizzle/index.js +1212 -0
  29. package/dist/drizzle/index.js.map +1 -0
  30. package/dist/dynamodb/index.cjs +382 -0
  31. package/dist/dynamodb/index.cjs.map +1 -0
  32. package/dist/dynamodb/index.d.cts +125 -0
  33. package/dist/dynamodb/index.d.ts +125 -0
  34. package/dist/dynamodb/index.js +355 -0
  35. package/dist/dynamodb/index.js.map +1 -0
  36. package/dist/identity/index.cjs +271 -0
  37. package/dist/identity/index.cjs.map +1 -0
  38. package/dist/identity/index.d.cts +3 -0
  39. package/dist/identity/index.d.ts +3 -0
  40. package/dist/identity/index.js +117 -0
  41. package/dist/identity/index.js.map +1 -0
  42. package/dist/index-9-Ya3fDK.d.cts +169 -0
  43. package/dist/index-9-Ya3fDK.d.ts +169 -0
  44. package/dist/index.cjs +2915 -0
  45. package/dist/index.cjs.map +1 -0
  46. package/dist/index.d.cts +22 -0
  47. package/dist/index.d.ts +22 -0
  48. package/dist/index.js +23 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/schema/index.cjs +368 -0
  51. package/dist/schema/index.cjs.map +1 -0
  52. package/dist/schema/index.d.cts +4 -0
  53. package/dist/schema/index.d.ts +4 -0
  54. package/dist/schema/index.js +23 -0
  55. package/dist/schema/index.js.map +1 -0
  56. package/dist/secrets/index.cjs +3207 -0
  57. package/dist/secrets/index.cjs.map +1 -0
  58. package/dist/secrets/index.d.cts +227 -0
  59. package/dist/secrets/index.d.ts +227 -0
  60. package/dist/secrets/index.js +323 -0
  61. package/dist/secrets/index.js.map +1 -0
  62. package/dist/supabase/index.cjs +1113 -0
  63. package/dist/supabase/index.cjs.map +1 -0
  64. package/dist/supabase/index.d.cts +144 -0
  65. package/dist/supabase/index.d.ts +144 -0
  66. package/dist/supabase/index.js +864 -0
  67. package/dist/supabase/index.js.map +1 -0
  68. package/dist/types-public-BCj1L4fi.d.cts +1013 -0
  69. package/dist/types-public-BCj1L4fi.d.ts +1013 -0
  70. package/dist/types-public.cjs +40 -0
  71. package/dist/types-public.cjs.map +1 -0
  72. package/dist/types-public.d.cts +4 -0
  73. package/dist/types-public.d.ts +4 -0
  74. package/dist/types-public.js +7 -0
  75. package/dist/types-public.js.map +1 -0
  76. package/package.json +202 -0
@@ -0,0 +1,1528 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc2) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/drizzle/index.ts
21
+ var drizzle_exports = {};
22
+ __export(drizzle_exports, {
23
+ EncryptionConfigError: () => EncryptionConfigError,
24
+ EncryptionOperatorError: () => EncryptionOperatorError,
25
+ createEncryptionOperators: () => createEncryptionOperators,
26
+ encryptedType: () => encryptedType,
27
+ extractEncryptionSchema: () => extractEncryptionSchema,
28
+ getEncryptedColumnConfig: () => getEncryptedColumnConfig
29
+ });
30
+ module.exports = __toCommonJS(drizzle_exports);
31
+ var import_pg_core = require("drizzle-orm/pg-core");
32
+
33
+ // src/schema/index.ts
34
+ var import_zod = require("zod");
35
+ var castAsEnum = import_zod.z.enum(["bigint", "boolean", "date", "number", "string", "json"]).default("string");
36
+ var tokenFilterSchema = import_zod.z.object({
37
+ kind: import_zod.z.literal("downcase")
38
+ });
39
+ var tokenizerSchema = import_zod.z.union([
40
+ import_zod.z.object({
41
+ kind: import_zod.z.literal("standard")
42
+ }),
43
+ import_zod.z.object({
44
+ kind: import_zod.z.literal("ngram"),
45
+ token_length: import_zod.z.number()
46
+ })
47
+ ]).default({ kind: "ngram", token_length: 3 }).optional();
48
+ var oreIndexOptsSchema = import_zod.z.object({});
49
+ var uniqueIndexOptsSchema = import_zod.z.object({
50
+ token_filters: import_zod.z.array(tokenFilterSchema).default([]).optional()
51
+ });
52
+ var matchIndexOptsSchema = import_zod.z.object({
53
+ tokenizer: tokenizerSchema,
54
+ token_filters: import_zod.z.array(tokenFilterSchema).default([]).optional(),
55
+ k: import_zod.z.number().default(6).optional(),
56
+ m: import_zod.z.number().default(2048).optional(),
57
+ include_original: import_zod.z.boolean().default(false).optional()
58
+ });
59
+ var steVecIndexOptsSchema = import_zod.z.object({
60
+ prefix: import_zod.z.string()
61
+ });
62
+ var indexesSchema = import_zod.z.object({
63
+ ore: oreIndexOptsSchema.optional(),
64
+ unique: uniqueIndexOptsSchema.optional(),
65
+ match: matchIndexOptsSchema.optional(),
66
+ ste_vec: steVecIndexOptsSchema.optional()
67
+ }).default({});
68
+ var columnSchema = import_zod.z.object({
69
+ cast_as: castAsEnum,
70
+ indexes: indexesSchema
71
+ }).default({});
72
+ var tableSchema = import_zod.z.record(columnSchema).default({});
73
+ var tablesSchema = import_zod.z.record(tableSchema).default({});
74
+ var encryptConfigSchema = import_zod.z.object({
75
+ v: import_zod.z.number(),
76
+ tables: tablesSchema
77
+ });
78
+ var ProtectValue = class {
79
+ valueName;
80
+ castAsValue;
81
+ constructor(valueName) {
82
+ this.valueName = valueName;
83
+ this.castAsValue = "string";
84
+ }
85
+ /**
86
+ * Set or override the plaintext data type for this value.
87
+ *
88
+ * By default all values are treated as `'string'`. Use this method to specify
89
+ * a different type so the encryption layer knows how to encode the plaintext
90
+ * before encrypting.
91
+ *
92
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
93
+ * @returns This `ProtectValue` instance for method chaining.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * import { encryptedValue } from "@cipherstash/stack/schema"
98
+ *
99
+ * const age = encryptedValue("age").dataType("number")
100
+ * ```
101
+ */
102
+ dataType(castAs) {
103
+ this.castAsValue = castAs;
104
+ return this;
105
+ }
106
+ build() {
107
+ return {
108
+ cast_as: this.castAsValue,
109
+ indexes: {}
110
+ };
111
+ }
112
+ getName() {
113
+ return this.valueName;
114
+ }
115
+ };
116
+ var ProtectColumn = class {
117
+ columnName;
118
+ castAsValue;
119
+ indexesValue = {};
120
+ constructor(columnName) {
121
+ this.columnName = columnName;
122
+ this.castAsValue = "string";
123
+ }
124
+ /**
125
+ * Set or override the plaintext data type for this column.
126
+ *
127
+ * By default all columns are treated as `'string'`. Use this method to specify
128
+ * a different type so the encryption layer knows how to encode the plaintext
129
+ * before encrypting.
130
+ *
131
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
132
+ * @returns This `ProtectColumn` instance for method chaining.
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * import { encryptedColumn } from "@cipherstash/stack/schema"
137
+ *
138
+ * const dateOfBirth = encryptedColumn("date_of_birth").dataType("date")
139
+ * ```
140
+ */
141
+ dataType(castAs) {
142
+ this.castAsValue = castAs;
143
+ return this;
144
+ }
145
+ /**
146
+ * Enable Order-Revealing Encryption (ORE) indexing on this column.
147
+ *
148
+ * ORE allows sorting, comparison, and range queries on encrypted data.
149
+ * Use with `encryptQuery` and `queryType: 'orderAndRange'`.
150
+ *
151
+ * @returns This `ProtectColumn` instance for method chaining.
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
156
+ *
157
+ * const users = encryptedTable("users", {
158
+ * email: encryptedColumn("email").orderAndRange(),
159
+ * })
160
+ * ```
161
+ */
162
+ orderAndRange() {
163
+ this.indexesValue.ore = {};
164
+ return this;
165
+ }
166
+ /**
167
+ * Enable an exact-match (unique) index on this column.
168
+ *
169
+ * Allows equality queries on encrypted data. Use with `encryptQuery`
170
+ * and `queryType: 'equality'`.
171
+ *
172
+ * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).
173
+ * When omitted, no token filters are applied.
174
+ * @returns This `ProtectColumn` instance for method chaining.
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
179
+ *
180
+ * const users = encryptedTable("users", {
181
+ * email: encryptedColumn("email").equality(),
182
+ * })
183
+ * ```
184
+ */
185
+ equality(tokenFilters) {
186
+ this.indexesValue.unique = {
187
+ token_filters: tokenFilters ?? []
188
+ };
189
+ return this;
190
+ }
191
+ /**
192
+ * Enable a full-text / fuzzy search (match) index on this column.
193
+ *
194
+ * Uses n-gram tokenization by default for substring and fuzzy matching.
195
+ * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.
196
+ *
197
+ * @param opts - Optional match index configuration. Defaults to 3-character ngram
198
+ * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.
199
+ * @returns This `ProtectColumn` instance for method chaining.
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
204
+ *
205
+ * const users = encryptedTable("users", {
206
+ * email: encryptedColumn("email").freeTextSearch(),
207
+ * })
208
+ *
209
+ * // With custom options
210
+ * const posts = encryptedTable("posts", {
211
+ * body: encryptedColumn("body").freeTextSearch({
212
+ * tokenizer: { kind: "ngram", token_length: 4 },
213
+ * k: 8,
214
+ * m: 4096,
215
+ * }),
216
+ * })
217
+ * ```
218
+ */
219
+ freeTextSearch(opts) {
220
+ this.indexesValue.match = {
221
+ tokenizer: opts?.tokenizer ?? { kind: "ngram", token_length: 3 },
222
+ token_filters: opts?.token_filters ?? [
223
+ {
224
+ kind: "downcase"
225
+ }
226
+ ],
227
+ k: opts?.k ?? 6,
228
+ m: opts?.m ?? 2048,
229
+ include_original: opts?.include_original ?? true
230
+ };
231
+ return this;
232
+ }
233
+ /**
234
+ * Configure this column for searchable encrypted JSON (STE-Vec).
235
+ *
236
+ * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and
237
+ * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the
238
+ * data type to `'json'`.
239
+ *
240
+ * When used with `encryptQuery`, the query operation is auto-inferred from
241
+ * the plaintext type: strings become selector queries, objects/arrays become
242
+ * containment queries.
243
+ *
244
+ * @returns This `ProtectColumn` instance for method chaining.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
249
+ *
250
+ * const documents = encryptedTable("documents", {
251
+ * metadata: encryptedColumn("metadata").searchableJson(),
252
+ * })
253
+ * ```
254
+ */
255
+ searchableJson() {
256
+ this.castAsValue = "json";
257
+ this.indexesValue.ste_vec = { prefix: "enabled" };
258
+ return this;
259
+ }
260
+ build() {
261
+ return {
262
+ cast_as: this.castAsValue,
263
+ indexes: this.indexesValue
264
+ };
265
+ }
266
+ getName() {
267
+ return this.columnName;
268
+ }
269
+ };
270
+ var ProtectTable = class {
271
+ constructor(tableName, columnBuilders) {
272
+ this.tableName = tableName;
273
+ this.columnBuilders = columnBuilders;
274
+ }
275
+ /**
276
+ * Compile this table schema into a `TableDefinition` used internally by the encryption client.
277
+ *
278
+ * Iterates over all column builders, calls `.build()` on each, and assembles
279
+ * the final `{ tableName, columns }` structure. For `searchableJson()` columns,
280
+ * the STE-Vec prefix is automatically set to `"<tableName>/<columnName>"`.
281
+ *
282
+ * @returns A `TableDefinition` containing the table name and built column configs.
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * const users = encryptedTable("users", {
287
+ * email: encryptedColumn("email").equality(),
288
+ * })
289
+ *
290
+ * const definition = users.build()
291
+ * // { tableName: "users", columns: { email: { cast_as: "string", indexes: { unique: ... } } } }
292
+ * ```
293
+ */
294
+ build() {
295
+ const builtColumns = {};
296
+ const processColumn = (builder, colName) => {
297
+ if (builder instanceof ProtectColumn) {
298
+ const builtColumn = builder.build();
299
+ if (builtColumn.cast_as === "json" && builtColumn.indexes.ste_vec?.prefix === "enabled") {
300
+ builtColumns[colName] = {
301
+ ...builtColumn,
302
+ indexes: {
303
+ ...builtColumn.indexes,
304
+ ste_vec: {
305
+ prefix: `${this.tableName}/${colName}`
306
+ }
307
+ }
308
+ };
309
+ } else {
310
+ builtColumns[colName] = builtColumn;
311
+ }
312
+ } else {
313
+ for (const [key, value] of Object.entries(builder)) {
314
+ if (value instanceof ProtectValue) {
315
+ builtColumns[value.getName()] = value.build();
316
+ } else {
317
+ processColumn(value, key);
318
+ }
319
+ }
320
+ }
321
+ };
322
+ for (const [colName, builder] of Object.entries(this.columnBuilders)) {
323
+ processColumn(builder, colName);
324
+ }
325
+ return {
326
+ tableName: this.tableName,
327
+ columns: builtColumns
328
+ };
329
+ }
330
+ };
331
+ function encryptedTable(tableName, columns) {
332
+ const tableBuilder = new ProtectTable(tableName, columns);
333
+ for (const [colName, colBuilder] of Object.entries(columns)) {
334
+ ;
335
+ tableBuilder[colName] = colBuilder;
336
+ }
337
+ return tableBuilder;
338
+ }
339
+ function encryptedColumn(columnName) {
340
+ return new ProtectColumn(columnName);
341
+ }
342
+
343
+ // src/drizzle/schema-extraction.ts
344
+ function extractEncryptionSchema(table) {
345
+ const tableName = table[Symbol.for("drizzle:Name")];
346
+ if (!tableName) {
347
+ throw new Error(
348
+ "Unable to extract table name from Drizzle table. Ensure you are using a table created with pgTable()."
349
+ );
350
+ }
351
+ const columns = {};
352
+ for (const [columnName, column] of Object.entries(table)) {
353
+ if (typeof column !== "object" || column === null) {
354
+ continue;
355
+ }
356
+ const config = getEncryptedColumnConfig(columnName, column);
357
+ if (config) {
358
+ const actualColumnName = column.name || config.name;
359
+ const csCol = encryptedColumn(actualColumnName);
360
+ if (config.dataType && config.dataType !== "string") {
361
+ csCol.dataType(config.dataType);
362
+ }
363
+ if (config.orderAndRange) {
364
+ csCol.orderAndRange();
365
+ }
366
+ if (config.equality) {
367
+ if (Array.isArray(config.equality)) {
368
+ csCol.equality(config.equality);
369
+ } else {
370
+ csCol.equality();
371
+ }
372
+ }
373
+ if (config.freeTextSearch) {
374
+ if (typeof config.freeTextSearch === "object") {
375
+ csCol.freeTextSearch(config.freeTextSearch);
376
+ } else {
377
+ csCol.freeTextSearch();
378
+ }
379
+ }
380
+ if (config.searchableJson) {
381
+ if (config.dataType !== "json") {
382
+ throw new Error(
383
+ `Column "${columnName}" has searchableJson enabled but dataType is "${config.dataType ?? "string"}". searchableJson requires dataType: 'json'.`
384
+ );
385
+ }
386
+ csCol.searchableJson();
387
+ }
388
+ columns[actualColumnName] = csCol;
389
+ }
390
+ }
391
+ if (Object.keys(columns).length === 0) {
392
+ throw new Error(
393
+ `No encrypted columns found in table "${tableName}". Use encryptedType() to define encrypted columns.`
394
+ );
395
+ }
396
+ return encryptedTable(tableName, columns);
397
+ }
398
+
399
+ // src/types.ts
400
+ var queryTypes = {
401
+ orderAndRange: "orderAndRange",
402
+ freeTextSearch: "freeTextSearch",
403
+ equality: "equality",
404
+ steVecSelector: "steVecSelector",
405
+ steVecTerm: "steVecTerm",
406
+ searchableJson: "searchableJson"
407
+ };
408
+
409
+ // src/drizzle/operators.ts
410
+ var import_drizzle_orm = require("drizzle-orm");
411
+ var import_drizzle_orm2 = require("drizzle-orm");
412
+ function isSQLWrapper(value) {
413
+ return typeof value === "object" && value !== null && "sql" in value && typeof value.sql !== "undefined";
414
+ }
415
+ function isPgTable(value) {
416
+ return typeof value === "object" && value !== null && Symbol.for("drizzle:Name") in value;
417
+ }
418
+ var EncryptionOperatorError = class extends Error {
419
+ constructor(message, context) {
420
+ super(message);
421
+ this.context = context;
422
+ this.name = "EncryptionOperatorError";
423
+ }
424
+ };
425
+ var EncryptionConfigError = class extends EncryptionOperatorError {
426
+ constructor(message, context) {
427
+ super(message, context);
428
+ this.name = "EncryptionConfigError";
429
+ }
430
+ };
431
+ function getDrizzleTableName(drizzleTable) {
432
+ if (!isPgTable(drizzleTable)) {
433
+ return void 0;
434
+ }
435
+ const tableWithSymbol = drizzleTable;
436
+ return tableWithSymbol[Symbol.for("drizzle:Name")];
437
+ }
438
+ function getDrizzleTableFromColumn(drizzleColumn) {
439
+ const column = drizzleColumn;
440
+ return column.table;
441
+ }
442
+ function getEncryptedTableFromColumn(drizzleColumn, tableCache) {
443
+ const drizzleTable = getDrizzleTableFromColumn(drizzleColumn);
444
+ if (!drizzleTable) {
445
+ return void 0;
446
+ }
447
+ const tableName = getDrizzleTableName(drizzleTable);
448
+ if (!tableName) {
449
+ return void 0;
450
+ }
451
+ let encryptedTable2 = tableCache.get(tableName);
452
+ if (encryptedTable2) {
453
+ return encryptedTable2;
454
+ }
455
+ try {
456
+ encryptedTable2 = extractEncryptionSchema(drizzleTable);
457
+ tableCache.set(tableName, encryptedTable2);
458
+ return encryptedTable2;
459
+ } catch {
460
+ return void 0;
461
+ }
462
+ }
463
+ function getEncryptedColumn(drizzleColumn, encryptedTable2) {
464
+ const column = drizzleColumn;
465
+ const columnName = column.name;
466
+ if (!columnName) {
467
+ return void 0;
468
+ }
469
+ const tableRecord = encryptedTable2;
470
+ return tableRecord[columnName];
471
+ }
472
+ function getColumnInfo(drizzleColumn, encryptedTable2, tableCache) {
473
+ const column = drizzleColumn;
474
+ const columnName = column.name || "unknown";
475
+ let resolvedTable = encryptedTable2;
476
+ if (!resolvedTable) {
477
+ resolvedTable = getEncryptedTableFromColumn(drizzleColumn, tableCache);
478
+ }
479
+ const drizzleTable = getDrizzleTableFromColumn(drizzleColumn);
480
+ const tableName = getDrizzleTableName(drizzleTable);
481
+ if (!resolvedTable) {
482
+ const config2 = getEncryptedColumnConfig(columnName, drizzleColumn);
483
+ return {
484
+ encryptedColumn: void 0,
485
+ config: config2,
486
+ encryptedTable: void 0,
487
+ columnName,
488
+ tableName
489
+ };
490
+ }
491
+ const encryptedColumn2 = getEncryptedColumn(drizzleColumn, resolvedTable);
492
+ const config = getEncryptedColumnConfig(columnName, drizzleColumn);
493
+ return {
494
+ encryptedColumn: encryptedColumn2,
495
+ config,
496
+ encryptedTable: resolvedTable,
497
+ columnName,
498
+ tableName
499
+ };
500
+ }
501
+ function toPlaintext(value) {
502
+ if (typeof value === "boolean") {
503
+ return value ? 1 : 0;
504
+ }
505
+ if (typeof value === "string" || typeof value === "number") {
506
+ return value;
507
+ }
508
+ if (value instanceof Date) {
509
+ return value.toISOString();
510
+ }
511
+ return String(value);
512
+ }
513
+ async function encryptValues(encryptionClient, values, encryptedTable2, tableCache) {
514
+ if (values.length === 0) {
515
+ return [];
516
+ }
517
+ const valuesToEncrypt = [];
518
+ const results = new Array(values.length);
519
+ for (let i = 0; i < values.length; i++) {
520
+ const { value, column, queryType } = values[i];
521
+ const columnInfo = getColumnInfo(column, encryptedTable2, tableCache);
522
+ if (!columnInfo.encryptedColumn || !columnInfo.config || !columnInfo.encryptedTable) {
523
+ results[i] = value;
524
+ continue;
525
+ }
526
+ const plaintextValue = toPlaintext(value);
527
+ valuesToEncrypt.push({
528
+ value: plaintextValue,
529
+ column,
530
+ columnInfo,
531
+ queryType,
532
+ originalIndex: i
533
+ });
534
+ }
535
+ if (valuesToEncrypt.length === 0) {
536
+ return results;
537
+ }
538
+ const columnGroups = /* @__PURE__ */ new Map();
539
+ let valueIndex = 0;
540
+ for (const {
541
+ value,
542
+ columnInfo,
543
+ queryType,
544
+ originalIndex
545
+ } of valuesToEncrypt) {
546
+ if (!columnInfo.config || !columnInfo.encryptedColumn || !columnInfo.encryptedTable) {
547
+ continue;
548
+ }
549
+ const columnName = columnInfo.config.name;
550
+ const groupKey = `${columnInfo.tableName ?? "unknown"}/${columnName}`;
551
+ let group = columnGroups.get(groupKey);
552
+ if (!group) {
553
+ group = {
554
+ column: columnInfo.encryptedColumn,
555
+ table: columnInfo.encryptedTable,
556
+ columnName,
557
+ values: [],
558
+ resultIndices: []
559
+ };
560
+ columnGroups.set(groupKey, group);
561
+ }
562
+ group.values.push({ value, index: valueIndex++, queryType });
563
+ group.resultIndices.push(originalIndex);
564
+ }
565
+ for (const [, group] of columnGroups) {
566
+ const { columnName } = group;
567
+ try {
568
+ const terms = group.values.map((v) => ({
569
+ value: v.value,
570
+ column: group.column,
571
+ table: group.table,
572
+ queryType: v.queryType
573
+ }));
574
+ const encryptedTerms = await encryptionClient.encryptQuery(terms);
575
+ if (encryptedTerms.failure) {
576
+ throw new EncryptionOperatorError(
577
+ `Failed to encrypt query terms for column "${columnName}": ${encryptedTerms.failure.message}`,
578
+ { columnName }
579
+ );
580
+ }
581
+ for (let i = 0; i < group.values.length; i++) {
582
+ const resultIndex = group.resultIndices[i] ?? -1;
583
+ if (resultIndex >= 0 && resultIndex < results.length) {
584
+ results[resultIndex] = encryptedTerms.data[i];
585
+ }
586
+ }
587
+ } catch (error) {
588
+ if (error instanceof EncryptionOperatorError) {
589
+ throw error;
590
+ }
591
+ const errorMessage = error instanceof Error ? error.message : String(error);
592
+ throw new EncryptionOperatorError(
593
+ `Unexpected error encrypting values for column "${columnName}": ${errorMessage}`,
594
+ { columnName }
595
+ );
596
+ }
597
+ }
598
+ return results;
599
+ }
600
+ async function encryptValue(encryptionClient, value, drizzleColumn, encryptedTable2, tableCache, queryType) {
601
+ const results = await encryptValues(
602
+ encryptionClient,
603
+ [{ value, column: drizzleColumn, queryType }],
604
+ encryptedTable2,
605
+ tableCache
606
+ );
607
+ return results[0];
608
+ }
609
+ function isLazyOperator(value) {
610
+ return typeof value === "object" && value !== null && "__isLazyOperator" in value && value.__isLazyOperator === true;
611
+ }
612
+ function createLazyOperator(operator, left, right, execute, needsEncryption, columnInfo, encryptionClient, defaultTable, tableCache, min, max, queryType) {
613
+ let resolvedSQL;
614
+ let encryptionPromise;
615
+ const lazyOp = {
616
+ __isLazyOperator: true,
617
+ operator,
618
+ queryType,
619
+ left,
620
+ right,
621
+ min,
622
+ max,
623
+ needsEncryption,
624
+ columnInfo,
625
+ execute
626
+ };
627
+ const promise = new Promise((resolve, reject) => {
628
+ queueMicrotask(async () => {
629
+ if (resolvedSQL !== void 0) {
630
+ resolve(resolvedSQL);
631
+ return;
632
+ }
633
+ try {
634
+ if (!encryptionPromise) {
635
+ encryptionPromise = executeLazyOperatorDirect(
636
+ lazyOp,
637
+ encryptionClient,
638
+ defaultTable,
639
+ tableCache
640
+ );
641
+ }
642
+ const sql2 = await encryptionPromise;
643
+ resolvedSQL = sql2;
644
+ resolve(sql2);
645
+ } catch (error) {
646
+ reject(error);
647
+ }
648
+ });
649
+ });
650
+ return Object.assign(promise, lazyOp);
651
+ }
652
+ async function executeLazyOperator(lazyOp, encryptedValues) {
653
+ if (!lazyOp.needsEncryption) {
654
+ return lazyOp.execute(lazyOp.right);
655
+ }
656
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
657
+ let encryptedMin;
658
+ let encryptedMax;
659
+ if (encryptedValues && encryptedValues.length >= 2) {
660
+ encryptedMin = encryptedValues[0]?.encrypted;
661
+ encryptedMax = encryptedValues[1]?.encrypted;
662
+ } else {
663
+ throw new EncryptionOperatorError(
664
+ "Between operator requires both min and max encrypted values",
665
+ {
666
+ columnName: lazyOp.columnInfo.columnName,
667
+ tableName: lazyOp.columnInfo.tableName,
668
+ operator: lazyOp.operator
669
+ }
670
+ );
671
+ }
672
+ if (encryptedMin === void 0 || encryptedMax === void 0) {
673
+ throw new EncryptionOperatorError(
674
+ "Between operator requires both min and max values to be encrypted",
675
+ {
676
+ columnName: lazyOp.columnInfo.columnName,
677
+ tableName: lazyOp.columnInfo.tableName,
678
+ operator: lazyOp.operator
679
+ }
680
+ );
681
+ }
682
+ return lazyOp.execute(void 0, encryptedMin, encryptedMax);
683
+ }
684
+ let encrypted;
685
+ if (encryptedValues && encryptedValues.length > 0) {
686
+ encrypted = encryptedValues[0]?.encrypted;
687
+ } else {
688
+ throw new EncryptionOperatorError(
689
+ "Operator requires encrypted value but none provided",
690
+ {
691
+ columnName: lazyOp.columnInfo.columnName,
692
+ tableName: lazyOp.columnInfo.tableName,
693
+ operator: lazyOp.operator
694
+ }
695
+ );
696
+ }
697
+ if (encrypted === void 0) {
698
+ throw new EncryptionOperatorError(
699
+ "Encryption failed or value was not encrypted",
700
+ {
701
+ columnName: lazyOp.columnInfo.columnName,
702
+ tableName: lazyOp.columnInfo.tableName,
703
+ operator: lazyOp.operator
704
+ }
705
+ );
706
+ }
707
+ return lazyOp.execute(encrypted);
708
+ }
709
+ async function executeLazyOperatorDirect(lazyOp, encryptionClient, defaultTable, tableCache) {
710
+ if (!lazyOp.needsEncryption) {
711
+ return lazyOp.execute(lazyOp.right);
712
+ }
713
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
714
+ const [encryptedMin, encryptedMax] = await encryptValues(
715
+ encryptionClient,
716
+ [
717
+ { value: lazyOp.min, column: lazyOp.left, queryType: lazyOp.queryType },
718
+ { value: lazyOp.max, column: lazyOp.left, queryType: lazyOp.queryType }
719
+ ],
720
+ defaultTable,
721
+ tableCache
722
+ );
723
+ return lazyOp.execute(void 0, encryptedMin, encryptedMax);
724
+ }
725
+ const encrypted = await encryptValue(
726
+ encryptionClient,
727
+ lazyOp.right,
728
+ lazyOp.left,
729
+ defaultTable,
730
+ tableCache,
731
+ lazyOp.queryType
732
+ );
733
+ return lazyOp.execute(encrypted);
734
+ }
735
+ function createComparisonOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
736
+ const { config } = columnInfo;
737
+ const requiresOrderAndRange = ["gt", "gte", "lt", "lte"].includes(operator);
738
+ if (requiresOrderAndRange) {
739
+ if (!config?.orderAndRange) {
740
+ switch (operator) {
741
+ case "gt":
742
+ return (0, import_drizzle_orm.gt)(left, right);
743
+ case "gte":
744
+ return (0, import_drizzle_orm.gte)(left, right);
745
+ case "lt":
746
+ return (0, import_drizzle_orm.lt)(left, right);
747
+ case "lte":
748
+ return (0, import_drizzle_orm.lte)(left, right);
749
+ }
750
+ }
751
+ const executeFn = (encrypted) => {
752
+ if (encrypted === void 0) {
753
+ throw new EncryptionOperatorError(
754
+ `Encryption failed for ${operator} operator`,
755
+ {
756
+ columnName: columnInfo.columnName,
757
+ tableName: columnInfo.tableName,
758
+ operator
759
+ }
760
+ );
761
+ }
762
+ return import_drizzle_orm2.sql`eql_v2.${import_drizzle_orm2.sql.raw(operator)}(${left}, ${(0, import_drizzle_orm2.bindIfParam)(encrypted, left)})`;
763
+ };
764
+ return createLazyOperator(
765
+ operator,
766
+ left,
767
+ right,
768
+ executeFn,
769
+ true,
770
+ columnInfo,
771
+ encryptionClient,
772
+ defaultTable,
773
+ tableCache,
774
+ void 0,
775
+ // min
776
+ void 0,
777
+ // max
778
+ queryTypes.orderAndRange
779
+ );
780
+ }
781
+ const requiresEquality = ["eq", "ne"].includes(operator);
782
+ if (requiresEquality && config?.equality) {
783
+ const executeFn = (encrypted) => {
784
+ if (encrypted === void 0) {
785
+ throw new EncryptionOperatorError(
786
+ `Encryption failed for ${operator} operator`,
787
+ {
788
+ columnName: columnInfo.columnName,
789
+ tableName: columnInfo.tableName,
790
+ operator
791
+ }
792
+ );
793
+ }
794
+ return operator === "eq" ? (0, import_drizzle_orm.eq)(left, encrypted) : (0, import_drizzle_orm.ne)(left, encrypted);
795
+ };
796
+ return createLazyOperator(
797
+ operator,
798
+ left,
799
+ right,
800
+ executeFn,
801
+ true,
802
+ columnInfo,
803
+ encryptionClient,
804
+ defaultTable,
805
+ tableCache,
806
+ void 0,
807
+ // min
808
+ void 0,
809
+ // max
810
+ queryTypes.equality
811
+ );
812
+ }
813
+ return operator === "eq" ? (0, import_drizzle_orm.eq)(left, right) : (0, import_drizzle_orm.ne)(left, right);
814
+ }
815
+ function createRangeOperator(operator, left, min, max, columnInfo, encryptionClient, defaultTable, tableCache) {
816
+ const { config } = columnInfo;
817
+ if (!config?.orderAndRange) {
818
+ return operator === "between" ? (0, import_drizzle_orm.between)(left, min, max) : (0, import_drizzle_orm.notBetween)(left, min, max);
819
+ }
820
+ const executeFn = (_encrypted, encryptedMin, encryptedMax) => {
821
+ if (encryptedMin === void 0 || encryptedMax === void 0) {
822
+ throw new EncryptionOperatorError(
823
+ `${operator} operator requires both min and max values`,
824
+ {
825
+ columnName: columnInfo.columnName,
826
+ tableName: columnInfo.tableName,
827
+ operator
828
+ }
829
+ );
830
+ }
831
+ const rangeCondition = import_drizzle_orm2.sql`eql_v2.gte(${left}, ${(0, import_drizzle_orm2.bindIfParam)(encryptedMin, left)}) AND eql_v2.lte(${left}, ${(0, import_drizzle_orm2.bindIfParam)(encryptedMax, left)})`;
832
+ return operator === "between" ? rangeCondition : import_drizzle_orm2.sql`NOT (${rangeCondition})`;
833
+ };
834
+ return createLazyOperator(
835
+ operator,
836
+ left,
837
+ void 0,
838
+ executeFn,
839
+ true,
840
+ columnInfo,
841
+ encryptionClient,
842
+ defaultTable,
843
+ tableCache,
844
+ min,
845
+ max,
846
+ queryTypes.orderAndRange
847
+ );
848
+ }
849
+ function createTextSearchOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
850
+ const { config } = columnInfo;
851
+ if (!config?.freeTextSearch) {
852
+ const rightValue = right;
853
+ switch (operator) {
854
+ case "like":
855
+ return (0, import_drizzle_orm.like)(left, rightValue);
856
+ case "ilike":
857
+ return (0, import_drizzle_orm.ilike)(left, rightValue);
858
+ case "notIlike":
859
+ return (0, import_drizzle_orm.notIlike)(left, rightValue);
860
+ }
861
+ }
862
+ const executeFn = (encrypted) => {
863
+ if (encrypted === void 0) {
864
+ throw new EncryptionOperatorError(
865
+ `Encryption failed for ${operator} operator`,
866
+ {
867
+ columnName: columnInfo.columnName,
868
+ tableName: columnInfo.tableName,
869
+ operator
870
+ }
871
+ );
872
+ }
873
+ const sqlFn = import_drizzle_orm2.sql`eql_v2.${import_drizzle_orm2.sql.raw(operator === "notIlike" ? "ilike" : operator)}(${left}, ${(0, import_drizzle_orm2.bindIfParam)(encrypted, left)})`;
874
+ return operator === "notIlike" ? import_drizzle_orm2.sql`NOT (${sqlFn})` : sqlFn;
875
+ };
876
+ return createLazyOperator(
877
+ operator,
878
+ left,
879
+ right,
880
+ executeFn,
881
+ true,
882
+ columnInfo,
883
+ encryptionClient,
884
+ defaultTable,
885
+ tableCache,
886
+ void 0,
887
+ // min
888
+ void 0,
889
+ // max
890
+ queryTypes.freeTextSearch
891
+ );
892
+ }
893
+ function createJsonbOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
894
+ const { config } = columnInfo;
895
+ const encryptedSelector = (value) => import_drizzle_orm2.sql`${(0, import_drizzle_orm2.bindIfParam)(value, left)}::eql_v2_encrypted`;
896
+ if (!config?.searchableJson) {
897
+ throw new EncryptionOperatorError(
898
+ `The ${operator} operator requires searchableJson to be enabled on the column configuration.`,
899
+ {
900
+ columnName: columnInfo.columnName,
901
+ tableName: columnInfo.tableName,
902
+ operator
903
+ }
904
+ );
905
+ }
906
+ const executeFn = (encrypted) => {
907
+ if (encrypted === void 0) {
908
+ throw new EncryptionOperatorError(
909
+ `Encryption failed for ${operator} operator`,
910
+ {
911
+ columnName: columnInfo.columnName,
912
+ tableName: columnInfo.tableName,
913
+ operator
914
+ }
915
+ );
916
+ }
917
+ switch (operator) {
918
+ case "jsonbPathQueryFirst":
919
+ return import_drizzle_orm2.sql`eql_v2.jsonb_path_query_first(${left}, ${encryptedSelector(encrypted)})`;
920
+ case "jsonbGet":
921
+ return import_drizzle_orm2.sql`${left} -> ${encryptedSelector(encrypted)}`;
922
+ case "jsonbPathExists":
923
+ return import_drizzle_orm2.sql`eql_v2.jsonb_path_exists(${left}, ${encryptedSelector(encrypted)})`;
924
+ }
925
+ };
926
+ return createLazyOperator(
927
+ operator,
928
+ left,
929
+ right,
930
+ executeFn,
931
+ true,
932
+ columnInfo,
933
+ encryptionClient,
934
+ defaultTable,
935
+ tableCache,
936
+ void 0,
937
+ void 0,
938
+ queryTypes.steVecSelector
939
+ );
940
+ }
941
+ function createEncryptionOperators(encryptionClient) {
942
+ const tableCache = /* @__PURE__ */ new Map();
943
+ const defaultTable = void 0;
944
+ const encryptedEq = (left, right) => {
945
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
946
+ return createComparisonOperator(
947
+ "eq",
948
+ left,
949
+ right,
950
+ columnInfo,
951
+ encryptionClient,
952
+ defaultTable,
953
+ tableCache
954
+ );
955
+ };
956
+ const encryptedNe = (left, right) => {
957
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
958
+ return createComparisonOperator(
959
+ "ne",
960
+ left,
961
+ right,
962
+ columnInfo,
963
+ encryptionClient,
964
+ defaultTable,
965
+ tableCache
966
+ );
967
+ };
968
+ const encryptedGt = (left, right) => {
969
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
970
+ return createComparisonOperator(
971
+ "gt",
972
+ left,
973
+ right,
974
+ columnInfo,
975
+ encryptionClient,
976
+ defaultTable,
977
+ tableCache
978
+ );
979
+ };
980
+ const encryptedGte = (left, right) => {
981
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
982
+ return createComparisonOperator(
983
+ "gte",
984
+ left,
985
+ right,
986
+ columnInfo,
987
+ encryptionClient,
988
+ defaultTable,
989
+ tableCache
990
+ );
991
+ };
992
+ const encryptedLt = (left, right) => {
993
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
994
+ return createComparisonOperator(
995
+ "lt",
996
+ left,
997
+ right,
998
+ columnInfo,
999
+ encryptionClient,
1000
+ defaultTable,
1001
+ tableCache
1002
+ );
1003
+ };
1004
+ const encryptedLte = (left, right) => {
1005
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1006
+ return createComparisonOperator(
1007
+ "lte",
1008
+ left,
1009
+ right,
1010
+ columnInfo,
1011
+ encryptionClient,
1012
+ defaultTable,
1013
+ tableCache
1014
+ );
1015
+ };
1016
+ const encryptedBetween = (left, min, max) => {
1017
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1018
+ return createRangeOperator(
1019
+ "between",
1020
+ left,
1021
+ min,
1022
+ max,
1023
+ columnInfo,
1024
+ encryptionClient,
1025
+ defaultTable,
1026
+ tableCache
1027
+ );
1028
+ };
1029
+ const encryptedNotBetween = (left, min, max) => {
1030
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1031
+ return createRangeOperator(
1032
+ "notBetween",
1033
+ left,
1034
+ min,
1035
+ max,
1036
+ columnInfo,
1037
+ encryptionClient,
1038
+ defaultTable,
1039
+ tableCache
1040
+ );
1041
+ };
1042
+ const encryptedLike = (left, right) => {
1043
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1044
+ return createTextSearchOperator(
1045
+ "like",
1046
+ left,
1047
+ right,
1048
+ columnInfo,
1049
+ encryptionClient,
1050
+ defaultTable,
1051
+ tableCache
1052
+ );
1053
+ };
1054
+ const encryptedIlike = (left, right) => {
1055
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1056
+ return createTextSearchOperator(
1057
+ "ilike",
1058
+ left,
1059
+ right,
1060
+ columnInfo,
1061
+ encryptionClient,
1062
+ defaultTable,
1063
+ tableCache
1064
+ );
1065
+ };
1066
+ const encryptedNotIlike = (left, right) => {
1067
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1068
+ return createTextSearchOperator(
1069
+ "notIlike",
1070
+ left,
1071
+ right,
1072
+ columnInfo,
1073
+ encryptionClient,
1074
+ defaultTable,
1075
+ tableCache
1076
+ );
1077
+ };
1078
+ const encryptedJsonbPathQueryFirst = (left, right) => {
1079
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1080
+ return createJsonbOperator(
1081
+ "jsonbPathQueryFirst",
1082
+ left,
1083
+ right,
1084
+ columnInfo,
1085
+ encryptionClient,
1086
+ defaultTable,
1087
+ tableCache
1088
+ );
1089
+ };
1090
+ const encryptedJsonbGet = (left, right) => {
1091
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1092
+ return createJsonbOperator(
1093
+ "jsonbGet",
1094
+ left,
1095
+ right,
1096
+ columnInfo,
1097
+ encryptionClient,
1098
+ defaultTable,
1099
+ tableCache
1100
+ );
1101
+ };
1102
+ const encryptedJsonbPathExists = (left, right) => {
1103
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1104
+ return createJsonbOperator(
1105
+ "jsonbPathExists",
1106
+ left,
1107
+ right,
1108
+ columnInfo,
1109
+ encryptionClient,
1110
+ defaultTable,
1111
+ tableCache
1112
+ );
1113
+ };
1114
+ const encryptedInArray = async (left, right) => {
1115
+ if (isSQLWrapper(right)) {
1116
+ return (0, import_drizzle_orm.inArray)(left, right);
1117
+ }
1118
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1119
+ if (!columnInfo.config?.equality || !Array.isArray(right)) {
1120
+ return (0, import_drizzle_orm.inArray)(left, right);
1121
+ }
1122
+ const encryptedValues = await encryptValues(
1123
+ encryptionClient,
1124
+ right.map((value) => ({
1125
+ value,
1126
+ column: left,
1127
+ queryType: queryTypes.equality
1128
+ })),
1129
+ defaultTable,
1130
+ tableCache
1131
+ );
1132
+ const conditions = encryptedValues.filter((encrypted) => encrypted !== void 0).map((encrypted) => (0, import_drizzle_orm.eq)(left, encrypted));
1133
+ if (conditions.length === 0) {
1134
+ return import_drizzle_orm2.sql`false`;
1135
+ }
1136
+ const combined = (0, import_drizzle_orm.or)(...conditions);
1137
+ return combined ?? import_drizzle_orm2.sql`false`;
1138
+ };
1139
+ const encryptedNotInArray = async (left, right) => {
1140
+ if (isSQLWrapper(right)) {
1141
+ return (0, import_drizzle_orm.notInArray)(
1142
+ left,
1143
+ right
1144
+ );
1145
+ }
1146
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
1147
+ if (!columnInfo.config?.equality || !Array.isArray(right)) {
1148
+ return (0, import_drizzle_orm.notInArray)(left, right);
1149
+ }
1150
+ const encryptedValues = await encryptValues(
1151
+ encryptionClient,
1152
+ right.map((value) => ({
1153
+ value,
1154
+ column: left,
1155
+ queryType: queryTypes.equality
1156
+ })),
1157
+ defaultTable,
1158
+ tableCache
1159
+ );
1160
+ const conditions = encryptedValues.filter((encrypted) => encrypted !== void 0).map((encrypted) => (0, import_drizzle_orm.ne)(left, encrypted));
1161
+ if (conditions.length === 0) {
1162
+ return import_drizzle_orm2.sql`true`;
1163
+ }
1164
+ const combined = (0, import_drizzle_orm.and)(...conditions);
1165
+ return combined ?? import_drizzle_orm2.sql`true`;
1166
+ };
1167
+ const encryptedAsc = (column) => {
1168
+ const columnInfo = getColumnInfo(column, defaultTable, tableCache);
1169
+ if (columnInfo.config?.orderAndRange) {
1170
+ return (0, import_drizzle_orm.asc)(import_drizzle_orm2.sql`eql_v2.order_by(${column})`);
1171
+ }
1172
+ return (0, import_drizzle_orm.asc)(column);
1173
+ };
1174
+ const encryptedDesc = (column) => {
1175
+ const columnInfo = getColumnInfo(column, defaultTable, tableCache);
1176
+ if (columnInfo.config?.orderAndRange) {
1177
+ return (0, import_drizzle_orm.desc)(import_drizzle_orm2.sql`eql_v2.order_by(${column})`);
1178
+ }
1179
+ return (0, import_drizzle_orm.desc)(column);
1180
+ };
1181
+ const encryptedAnd = async (...conditions) => {
1182
+ const lazyOperators = [];
1183
+ const regularConditions = [];
1184
+ const regularPromises = [];
1185
+ for (const condition of conditions) {
1186
+ if (condition === void 0) {
1187
+ continue;
1188
+ }
1189
+ if (isLazyOperator(condition)) {
1190
+ lazyOperators.push(condition);
1191
+ } else if (condition instanceof Promise) {
1192
+ if (isLazyOperator(condition)) {
1193
+ lazyOperators.push(condition);
1194
+ } else {
1195
+ regularPromises.push(condition);
1196
+ }
1197
+ } else {
1198
+ regularConditions.push(condition);
1199
+ }
1200
+ }
1201
+ if (lazyOperators.length === 0) {
1202
+ const allConditions2 = [
1203
+ ...regularConditions,
1204
+ ...await Promise.all(regularPromises)
1205
+ ];
1206
+ return (0, import_drizzle_orm.and)(...allConditions2) ?? import_drizzle_orm2.sql`true`;
1207
+ }
1208
+ const valuesToEncrypt = [];
1209
+ for (let i = 0; i < lazyOperators.length; i++) {
1210
+ const lazyOp = lazyOperators[i];
1211
+ if (!lazyOp.needsEncryption) {
1212
+ continue;
1213
+ }
1214
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
1215
+ valuesToEncrypt.push({
1216
+ value: lazyOp.min,
1217
+ column: lazyOp.left,
1218
+ columnInfo: lazyOp.columnInfo,
1219
+ queryType: lazyOp.queryType,
1220
+ lazyOpIndex: i,
1221
+ isMin: true
1222
+ });
1223
+ valuesToEncrypt.push({
1224
+ value: lazyOp.max,
1225
+ column: lazyOp.left,
1226
+ columnInfo: lazyOp.columnInfo,
1227
+ queryType: lazyOp.queryType,
1228
+ lazyOpIndex: i,
1229
+ isMax: true
1230
+ });
1231
+ } else if (lazyOp.right !== void 0) {
1232
+ valuesToEncrypt.push({
1233
+ value: lazyOp.right,
1234
+ column: lazyOp.left,
1235
+ columnInfo: lazyOp.columnInfo,
1236
+ queryType: lazyOp.queryType,
1237
+ lazyOpIndex: i
1238
+ });
1239
+ }
1240
+ }
1241
+ const encryptedResults = await encryptValues(
1242
+ encryptionClient,
1243
+ valuesToEncrypt.map((v) => ({
1244
+ value: v.value,
1245
+ column: v.column,
1246
+ queryType: v.queryType
1247
+ })),
1248
+ defaultTable,
1249
+ tableCache
1250
+ );
1251
+ const encryptedByLazyOp = /* @__PURE__ */ new Map();
1252
+ for (let i = 0; i < valuesToEncrypt.length; i++) {
1253
+ const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i];
1254
+ const encrypted = encryptedResults[i];
1255
+ let group = encryptedByLazyOp.get(lazyOpIndex);
1256
+ if (!group) {
1257
+ group = {};
1258
+ encryptedByLazyOp.set(lazyOpIndex, group);
1259
+ }
1260
+ if (isMin) {
1261
+ group.min = encrypted;
1262
+ } else if (isMax) {
1263
+ group.max = encrypted;
1264
+ } else {
1265
+ group.value = encrypted;
1266
+ }
1267
+ }
1268
+ const sqlConditions = [];
1269
+ for (let i = 0; i < lazyOperators.length; i++) {
1270
+ const lazyOp = lazyOperators[i];
1271
+ const encrypted = encryptedByLazyOp.get(i);
1272
+ let sqlCondition;
1273
+ if (lazyOp.needsEncryption && encrypted) {
1274
+ const encryptedValues = [];
1275
+ if (encrypted.value !== void 0) {
1276
+ encryptedValues.push({
1277
+ value: lazyOp.right,
1278
+ encrypted: encrypted.value
1279
+ });
1280
+ }
1281
+ if (encrypted.min !== void 0) {
1282
+ encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min });
1283
+ }
1284
+ if (encrypted.max !== void 0) {
1285
+ encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max });
1286
+ }
1287
+ sqlCondition = await executeLazyOperator(lazyOp, encryptedValues);
1288
+ } else {
1289
+ sqlCondition = lazyOp.execute(lazyOp.right);
1290
+ }
1291
+ sqlConditions.push(sqlCondition);
1292
+ }
1293
+ const regularPromisesResults = await Promise.all(regularPromises);
1294
+ const allConditions = [
1295
+ ...regularConditions,
1296
+ ...sqlConditions,
1297
+ ...regularPromisesResults
1298
+ ];
1299
+ return (0, import_drizzle_orm.and)(...allConditions) ?? import_drizzle_orm2.sql`true`;
1300
+ };
1301
+ const encryptedOr = async (...conditions) => {
1302
+ const lazyOperators = [];
1303
+ const regularConditions = [];
1304
+ const regularPromises = [];
1305
+ for (const condition of conditions) {
1306
+ if (condition === void 0) {
1307
+ continue;
1308
+ }
1309
+ if (isLazyOperator(condition)) {
1310
+ lazyOperators.push(condition);
1311
+ } else if (condition instanceof Promise) {
1312
+ if (isLazyOperator(condition)) {
1313
+ lazyOperators.push(condition);
1314
+ } else {
1315
+ regularPromises.push(condition);
1316
+ }
1317
+ } else {
1318
+ regularConditions.push(condition);
1319
+ }
1320
+ }
1321
+ if (lazyOperators.length === 0) {
1322
+ const allConditions2 = [
1323
+ ...regularConditions,
1324
+ ...await Promise.all(regularPromises)
1325
+ ];
1326
+ return (0, import_drizzle_orm.or)(...allConditions2) ?? import_drizzle_orm2.sql`false`;
1327
+ }
1328
+ const valuesToEncrypt = [];
1329
+ for (let i = 0; i < lazyOperators.length; i++) {
1330
+ const lazyOp = lazyOperators[i];
1331
+ if (!lazyOp.needsEncryption) {
1332
+ continue;
1333
+ }
1334
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
1335
+ valuesToEncrypt.push({
1336
+ value: lazyOp.min,
1337
+ column: lazyOp.left,
1338
+ columnInfo: lazyOp.columnInfo,
1339
+ queryType: lazyOp.queryType,
1340
+ lazyOpIndex: i,
1341
+ isMin: true
1342
+ });
1343
+ valuesToEncrypt.push({
1344
+ value: lazyOp.max,
1345
+ column: lazyOp.left,
1346
+ columnInfo: lazyOp.columnInfo,
1347
+ queryType: lazyOp.queryType,
1348
+ lazyOpIndex: i,
1349
+ isMax: true
1350
+ });
1351
+ } else if (lazyOp.right !== void 0) {
1352
+ valuesToEncrypt.push({
1353
+ value: lazyOp.right,
1354
+ column: lazyOp.left,
1355
+ columnInfo: lazyOp.columnInfo,
1356
+ queryType: lazyOp.queryType,
1357
+ lazyOpIndex: i
1358
+ });
1359
+ }
1360
+ }
1361
+ const encryptedResults = await encryptValues(
1362
+ encryptionClient,
1363
+ valuesToEncrypt.map((v) => ({
1364
+ value: v.value,
1365
+ column: v.column,
1366
+ queryType: v.queryType
1367
+ })),
1368
+ defaultTable,
1369
+ tableCache
1370
+ );
1371
+ const encryptedByLazyOp = /* @__PURE__ */ new Map();
1372
+ for (let i = 0; i < valuesToEncrypt.length; i++) {
1373
+ const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i];
1374
+ const encrypted = encryptedResults[i];
1375
+ let group = encryptedByLazyOp.get(lazyOpIndex);
1376
+ if (!group) {
1377
+ group = {};
1378
+ encryptedByLazyOp.set(lazyOpIndex, group);
1379
+ }
1380
+ if (isMin) {
1381
+ group.min = encrypted;
1382
+ } else if (isMax) {
1383
+ group.max = encrypted;
1384
+ } else {
1385
+ group.value = encrypted;
1386
+ }
1387
+ }
1388
+ const sqlConditions = [];
1389
+ for (let i = 0; i < lazyOperators.length; i++) {
1390
+ const lazyOp = lazyOperators[i];
1391
+ const encrypted = encryptedByLazyOp.get(i);
1392
+ let sqlCondition;
1393
+ if (lazyOp.needsEncryption && encrypted) {
1394
+ const encryptedValues = [];
1395
+ if (encrypted.value !== void 0) {
1396
+ encryptedValues.push({
1397
+ value: lazyOp.right,
1398
+ encrypted: encrypted.value
1399
+ });
1400
+ }
1401
+ if (encrypted.min !== void 0) {
1402
+ encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min });
1403
+ }
1404
+ if (encrypted.max !== void 0) {
1405
+ encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max });
1406
+ }
1407
+ sqlCondition = await executeLazyOperator(lazyOp, encryptedValues);
1408
+ } else {
1409
+ sqlCondition = lazyOp.execute(lazyOp.right);
1410
+ }
1411
+ sqlConditions.push(sqlCondition);
1412
+ }
1413
+ const regularPromisesResults = await Promise.all(regularPromises);
1414
+ const allConditions = [
1415
+ ...regularConditions,
1416
+ ...sqlConditions,
1417
+ ...regularPromisesResults
1418
+ ];
1419
+ return (0, import_drizzle_orm.or)(...allConditions) ?? import_drizzle_orm2.sql`false`;
1420
+ };
1421
+ return {
1422
+ // Comparison operators
1423
+ eq: encryptedEq,
1424
+ ne: encryptedNe,
1425
+ gt: encryptedGt,
1426
+ gte: encryptedGte,
1427
+ lt: encryptedLt,
1428
+ lte: encryptedLte,
1429
+ // Range operators
1430
+ between: encryptedBetween,
1431
+ notBetween: encryptedNotBetween,
1432
+ // Text search operators
1433
+ like: encryptedLike,
1434
+ ilike: encryptedIlike,
1435
+ notIlike: encryptedNotIlike,
1436
+ // Searchable JSON operators
1437
+ jsonbPathQueryFirst: encryptedJsonbPathQueryFirst,
1438
+ jsonbGet: encryptedJsonbGet,
1439
+ jsonbPathExists: encryptedJsonbPathExists,
1440
+ // Array operators
1441
+ inArray: encryptedInArray,
1442
+ notInArray: encryptedNotInArray,
1443
+ // Sorting operators
1444
+ asc: encryptedAsc,
1445
+ desc: encryptedDesc,
1446
+ // AND operator - batches encryption operations
1447
+ and: encryptedAnd,
1448
+ // OR operator - batches encryption operations
1449
+ or: encryptedOr,
1450
+ // Operators that don't need encryption (pass through to Drizzle)
1451
+ exists: import_drizzle_orm.exists,
1452
+ notExists: import_drizzle_orm.notExists,
1453
+ isNull: import_drizzle_orm.isNull,
1454
+ isNotNull: import_drizzle_orm.isNotNull,
1455
+ not: import_drizzle_orm.not,
1456
+ // Array operators that work with arrays directly (not encrypted values)
1457
+ arrayContains: import_drizzle_orm.arrayContains,
1458
+ arrayContained: import_drizzle_orm.arrayContained,
1459
+ arrayOverlaps: import_drizzle_orm.arrayOverlaps
1460
+ };
1461
+ }
1462
+
1463
+ // src/drizzle/index.ts
1464
+ var columnConfigMap = /* @__PURE__ */ new Map();
1465
+ var encryptedType = (name, config) => {
1466
+ const customColumnType = (0, import_pg_core.customType)({
1467
+ dataType() {
1468
+ return "eql_v2_encrypted";
1469
+ },
1470
+ toDriver(value) {
1471
+ const jsonStr = JSON.stringify(value);
1472
+ const escaped = jsonStr.replace(/"/g, '""');
1473
+ return `("${escaped}")`;
1474
+ },
1475
+ fromDriver(value) {
1476
+ const parseComposite = (str) => {
1477
+ if (!str || str === "") return null;
1478
+ const trimmed = str.trim();
1479
+ if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
1480
+ let inner = trimmed.slice(1, -1);
1481
+ inner = inner.replace(/""/g, '"');
1482
+ if (inner.startsWith('"') && inner.endsWith('"')) {
1483
+ const stripped = inner.slice(1, -1);
1484
+ return JSON.parse(stripped);
1485
+ }
1486
+ if (inner.startsWith("{") || inner.startsWith("[")) {
1487
+ return JSON.parse(inner);
1488
+ }
1489
+ return inner;
1490
+ }
1491
+ return JSON.parse(str);
1492
+ };
1493
+ return parseComposite(value);
1494
+ }
1495
+ });
1496
+ const column = customColumnType(name);
1497
+ const fullConfig = {
1498
+ name,
1499
+ ...config
1500
+ };
1501
+ columnConfigMap.set(name, fullConfig);
1502
+ column._encryptionConfig = fullConfig;
1503
+ return column;
1504
+ };
1505
+ function getEncryptedColumnConfig(columnName, column) {
1506
+ if (column && typeof column === "object") {
1507
+ const columnAny = column;
1508
+ const isEncrypted = columnAny.sqlName === "eql_v2_encrypted" || columnAny.dataType === "eql_v2_encrypted" || columnAny.dataType && typeof columnAny.dataType === "function" && columnAny.dataType() === "eql_v2_encrypted";
1509
+ if (isEncrypted) {
1510
+ if (columnAny._encryptionConfig) {
1511
+ return columnAny._encryptionConfig;
1512
+ }
1513
+ const lookupName = columnAny.name || columnName;
1514
+ return columnConfigMap.get(lookupName);
1515
+ }
1516
+ }
1517
+ return void 0;
1518
+ }
1519
+ // Annotate the CommonJS export names for ESM import in node:
1520
+ 0 && (module.exports = {
1521
+ EncryptionConfigError,
1522
+ EncryptionOperatorError,
1523
+ createEncryptionOperators,
1524
+ encryptedType,
1525
+ extractEncryptionSchema,
1526
+ getEncryptedColumnConfig
1527
+ });
1528
+ //# sourceMappingURL=index.cjs.map