@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,1212 @@
1
+ import {
2
+ queryTypes
3
+ } from "../chunk-SJ7JO4ME.js";
4
+ import {
5
+ encryptedColumn,
6
+ encryptedTable
7
+ } from "../chunk-7XRPN2KX.js";
8
+
9
+ // src/drizzle/index.ts
10
+ import { customType } from "drizzle-orm/pg-core";
11
+
12
+ // src/drizzle/schema-extraction.ts
13
+ function extractEncryptionSchema(table) {
14
+ const tableName = table[Symbol.for("drizzle:Name")];
15
+ if (!tableName) {
16
+ throw new Error(
17
+ "Unable to extract table name from Drizzle table. Ensure you are using a table created with pgTable()."
18
+ );
19
+ }
20
+ const columns = {};
21
+ for (const [columnName, column] of Object.entries(table)) {
22
+ if (typeof column !== "object" || column === null) {
23
+ continue;
24
+ }
25
+ const config = getEncryptedColumnConfig(columnName, column);
26
+ if (config) {
27
+ const actualColumnName = column.name || config.name;
28
+ const csCol = encryptedColumn(actualColumnName);
29
+ if (config.dataType && config.dataType !== "string") {
30
+ csCol.dataType(config.dataType);
31
+ }
32
+ if (config.orderAndRange) {
33
+ csCol.orderAndRange();
34
+ }
35
+ if (config.equality) {
36
+ if (Array.isArray(config.equality)) {
37
+ csCol.equality(config.equality);
38
+ } else {
39
+ csCol.equality();
40
+ }
41
+ }
42
+ if (config.freeTextSearch) {
43
+ if (typeof config.freeTextSearch === "object") {
44
+ csCol.freeTextSearch(config.freeTextSearch);
45
+ } else {
46
+ csCol.freeTextSearch();
47
+ }
48
+ }
49
+ if (config.searchableJson) {
50
+ if (config.dataType !== "json") {
51
+ throw new Error(
52
+ `Column "${columnName}" has searchableJson enabled but dataType is "${config.dataType ?? "string"}". searchableJson requires dataType: 'json'.`
53
+ );
54
+ }
55
+ csCol.searchableJson();
56
+ }
57
+ columns[actualColumnName] = csCol;
58
+ }
59
+ }
60
+ if (Object.keys(columns).length === 0) {
61
+ throw new Error(
62
+ `No encrypted columns found in table "${tableName}". Use encryptedType() to define encrypted columns.`
63
+ );
64
+ }
65
+ return encryptedTable(tableName, columns);
66
+ }
67
+
68
+ // src/drizzle/operators.ts
69
+ import {
70
+ and,
71
+ arrayContained,
72
+ arrayContains,
73
+ arrayOverlaps,
74
+ asc,
75
+ between,
76
+ desc,
77
+ eq,
78
+ exists,
79
+ gt,
80
+ gte,
81
+ ilike,
82
+ inArray,
83
+ isNotNull,
84
+ isNull,
85
+ like,
86
+ lt,
87
+ lte,
88
+ ne,
89
+ not,
90
+ notBetween,
91
+ notExists,
92
+ notIlike,
93
+ notInArray,
94
+ or
95
+ } from "drizzle-orm";
96
+ import { bindIfParam, sql } from "drizzle-orm";
97
+ function isSQLWrapper(value) {
98
+ return typeof value === "object" && value !== null && "sql" in value && typeof value.sql !== "undefined";
99
+ }
100
+ function isPgTable(value) {
101
+ return typeof value === "object" && value !== null && Symbol.for("drizzle:Name") in value;
102
+ }
103
+ var EncryptionOperatorError = class extends Error {
104
+ constructor(message, context) {
105
+ super(message);
106
+ this.context = context;
107
+ this.name = "EncryptionOperatorError";
108
+ }
109
+ };
110
+ var EncryptionConfigError = class extends EncryptionOperatorError {
111
+ constructor(message, context) {
112
+ super(message, context);
113
+ this.name = "EncryptionConfigError";
114
+ }
115
+ };
116
+ function getDrizzleTableName(drizzleTable) {
117
+ if (!isPgTable(drizzleTable)) {
118
+ return void 0;
119
+ }
120
+ const tableWithSymbol = drizzleTable;
121
+ return tableWithSymbol[Symbol.for("drizzle:Name")];
122
+ }
123
+ function getDrizzleTableFromColumn(drizzleColumn) {
124
+ const column = drizzleColumn;
125
+ return column.table;
126
+ }
127
+ function getEncryptedTableFromColumn(drizzleColumn, tableCache) {
128
+ const drizzleTable = getDrizzleTableFromColumn(drizzleColumn);
129
+ if (!drizzleTable) {
130
+ return void 0;
131
+ }
132
+ const tableName = getDrizzleTableName(drizzleTable);
133
+ if (!tableName) {
134
+ return void 0;
135
+ }
136
+ let encryptedTable2 = tableCache.get(tableName);
137
+ if (encryptedTable2) {
138
+ return encryptedTable2;
139
+ }
140
+ try {
141
+ encryptedTable2 = extractEncryptionSchema(drizzleTable);
142
+ tableCache.set(tableName, encryptedTable2);
143
+ return encryptedTable2;
144
+ } catch {
145
+ return void 0;
146
+ }
147
+ }
148
+ function getEncryptedColumn(drizzleColumn, encryptedTable2) {
149
+ const column = drizzleColumn;
150
+ const columnName = column.name;
151
+ if (!columnName) {
152
+ return void 0;
153
+ }
154
+ const tableRecord = encryptedTable2;
155
+ return tableRecord[columnName];
156
+ }
157
+ function getColumnInfo(drizzleColumn, encryptedTable2, tableCache) {
158
+ const column = drizzleColumn;
159
+ const columnName = column.name || "unknown";
160
+ let resolvedTable = encryptedTable2;
161
+ if (!resolvedTable) {
162
+ resolvedTable = getEncryptedTableFromColumn(drizzleColumn, tableCache);
163
+ }
164
+ const drizzleTable = getDrizzleTableFromColumn(drizzleColumn);
165
+ const tableName = getDrizzleTableName(drizzleTable);
166
+ if (!resolvedTable) {
167
+ const config2 = getEncryptedColumnConfig(columnName, drizzleColumn);
168
+ return {
169
+ encryptedColumn: void 0,
170
+ config: config2,
171
+ encryptedTable: void 0,
172
+ columnName,
173
+ tableName
174
+ };
175
+ }
176
+ const encryptedColumn2 = getEncryptedColumn(drizzleColumn, resolvedTable);
177
+ const config = getEncryptedColumnConfig(columnName, drizzleColumn);
178
+ return {
179
+ encryptedColumn: encryptedColumn2,
180
+ config,
181
+ encryptedTable: resolvedTable,
182
+ columnName,
183
+ tableName
184
+ };
185
+ }
186
+ function toPlaintext(value) {
187
+ if (typeof value === "boolean") {
188
+ return value ? 1 : 0;
189
+ }
190
+ if (typeof value === "string" || typeof value === "number") {
191
+ return value;
192
+ }
193
+ if (value instanceof Date) {
194
+ return value.toISOString();
195
+ }
196
+ return String(value);
197
+ }
198
+ async function encryptValues(encryptionClient, values, encryptedTable2, tableCache) {
199
+ if (values.length === 0) {
200
+ return [];
201
+ }
202
+ const valuesToEncrypt = [];
203
+ const results = new Array(values.length);
204
+ for (let i = 0; i < values.length; i++) {
205
+ const { value, column, queryType } = values[i];
206
+ const columnInfo = getColumnInfo(column, encryptedTable2, tableCache);
207
+ if (!columnInfo.encryptedColumn || !columnInfo.config || !columnInfo.encryptedTable) {
208
+ results[i] = value;
209
+ continue;
210
+ }
211
+ const plaintextValue = toPlaintext(value);
212
+ valuesToEncrypt.push({
213
+ value: plaintextValue,
214
+ column,
215
+ columnInfo,
216
+ queryType,
217
+ originalIndex: i
218
+ });
219
+ }
220
+ if (valuesToEncrypt.length === 0) {
221
+ return results;
222
+ }
223
+ const columnGroups = /* @__PURE__ */ new Map();
224
+ let valueIndex = 0;
225
+ for (const {
226
+ value,
227
+ columnInfo,
228
+ queryType,
229
+ originalIndex
230
+ } of valuesToEncrypt) {
231
+ if (!columnInfo.config || !columnInfo.encryptedColumn || !columnInfo.encryptedTable) {
232
+ continue;
233
+ }
234
+ const columnName = columnInfo.config.name;
235
+ const groupKey = `${columnInfo.tableName ?? "unknown"}/${columnName}`;
236
+ let group = columnGroups.get(groupKey);
237
+ if (!group) {
238
+ group = {
239
+ column: columnInfo.encryptedColumn,
240
+ table: columnInfo.encryptedTable,
241
+ columnName,
242
+ values: [],
243
+ resultIndices: []
244
+ };
245
+ columnGroups.set(groupKey, group);
246
+ }
247
+ group.values.push({ value, index: valueIndex++, queryType });
248
+ group.resultIndices.push(originalIndex);
249
+ }
250
+ for (const [, group] of columnGroups) {
251
+ const { columnName } = group;
252
+ try {
253
+ const terms = group.values.map((v) => ({
254
+ value: v.value,
255
+ column: group.column,
256
+ table: group.table,
257
+ queryType: v.queryType
258
+ }));
259
+ const encryptedTerms = await encryptionClient.encryptQuery(terms);
260
+ if (encryptedTerms.failure) {
261
+ throw new EncryptionOperatorError(
262
+ `Failed to encrypt query terms for column "${columnName}": ${encryptedTerms.failure.message}`,
263
+ { columnName }
264
+ );
265
+ }
266
+ for (let i = 0; i < group.values.length; i++) {
267
+ const resultIndex = group.resultIndices[i] ?? -1;
268
+ if (resultIndex >= 0 && resultIndex < results.length) {
269
+ results[resultIndex] = encryptedTerms.data[i];
270
+ }
271
+ }
272
+ } catch (error) {
273
+ if (error instanceof EncryptionOperatorError) {
274
+ throw error;
275
+ }
276
+ const errorMessage = error instanceof Error ? error.message : String(error);
277
+ throw new EncryptionOperatorError(
278
+ `Unexpected error encrypting values for column "${columnName}": ${errorMessage}`,
279
+ { columnName }
280
+ );
281
+ }
282
+ }
283
+ return results;
284
+ }
285
+ async function encryptValue(encryptionClient, value, drizzleColumn, encryptedTable2, tableCache, queryType) {
286
+ const results = await encryptValues(
287
+ encryptionClient,
288
+ [{ value, column: drizzleColumn, queryType }],
289
+ encryptedTable2,
290
+ tableCache
291
+ );
292
+ return results[0];
293
+ }
294
+ function isLazyOperator(value) {
295
+ return typeof value === "object" && value !== null && "__isLazyOperator" in value && value.__isLazyOperator === true;
296
+ }
297
+ function createLazyOperator(operator, left, right, execute, needsEncryption, columnInfo, encryptionClient, defaultTable, tableCache, min, max, queryType) {
298
+ let resolvedSQL;
299
+ let encryptionPromise;
300
+ const lazyOp = {
301
+ __isLazyOperator: true,
302
+ operator,
303
+ queryType,
304
+ left,
305
+ right,
306
+ min,
307
+ max,
308
+ needsEncryption,
309
+ columnInfo,
310
+ execute
311
+ };
312
+ const promise = new Promise((resolve, reject) => {
313
+ queueMicrotask(async () => {
314
+ if (resolvedSQL !== void 0) {
315
+ resolve(resolvedSQL);
316
+ return;
317
+ }
318
+ try {
319
+ if (!encryptionPromise) {
320
+ encryptionPromise = executeLazyOperatorDirect(
321
+ lazyOp,
322
+ encryptionClient,
323
+ defaultTable,
324
+ tableCache
325
+ );
326
+ }
327
+ const sql2 = await encryptionPromise;
328
+ resolvedSQL = sql2;
329
+ resolve(sql2);
330
+ } catch (error) {
331
+ reject(error);
332
+ }
333
+ });
334
+ });
335
+ return Object.assign(promise, lazyOp);
336
+ }
337
+ async function executeLazyOperator(lazyOp, encryptedValues) {
338
+ if (!lazyOp.needsEncryption) {
339
+ return lazyOp.execute(lazyOp.right);
340
+ }
341
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
342
+ let encryptedMin;
343
+ let encryptedMax;
344
+ if (encryptedValues && encryptedValues.length >= 2) {
345
+ encryptedMin = encryptedValues[0]?.encrypted;
346
+ encryptedMax = encryptedValues[1]?.encrypted;
347
+ } else {
348
+ throw new EncryptionOperatorError(
349
+ "Between operator requires both min and max encrypted values",
350
+ {
351
+ columnName: lazyOp.columnInfo.columnName,
352
+ tableName: lazyOp.columnInfo.tableName,
353
+ operator: lazyOp.operator
354
+ }
355
+ );
356
+ }
357
+ if (encryptedMin === void 0 || encryptedMax === void 0) {
358
+ throw new EncryptionOperatorError(
359
+ "Between operator requires both min and max values to be encrypted",
360
+ {
361
+ columnName: lazyOp.columnInfo.columnName,
362
+ tableName: lazyOp.columnInfo.tableName,
363
+ operator: lazyOp.operator
364
+ }
365
+ );
366
+ }
367
+ return lazyOp.execute(void 0, encryptedMin, encryptedMax);
368
+ }
369
+ let encrypted;
370
+ if (encryptedValues && encryptedValues.length > 0) {
371
+ encrypted = encryptedValues[0]?.encrypted;
372
+ } else {
373
+ throw new EncryptionOperatorError(
374
+ "Operator requires encrypted value but none provided",
375
+ {
376
+ columnName: lazyOp.columnInfo.columnName,
377
+ tableName: lazyOp.columnInfo.tableName,
378
+ operator: lazyOp.operator
379
+ }
380
+ );
381
+ }
382
+ if (encrypted === void 0) {
383
+ throw new EncryptionOperatorError(
384
+ "Encryption failed or value was not encrypted",
385
+ {
386
+ columnName: lazyOp.columnInfo.columnName,
387
+ tableName: lazyOp.columnInfo.tableName,
388
+ operator: lazyOp.operator
389
+ }
390
+ );
391
+ }
392
+ return lazyOp.execute(encrypted);
393
+ }
394
+ async function executeLazyOperatorDirect(lazyOp, encryptionClient, defaultTable, tableCache) {
395
+ if (!lazyOp.needsEncryption) {
396
+ return lazyOp.execute(lazyOp.right);
397
+ }
398
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
399
+ const [encryptedMin, encryptedMax] = await encryptValues(
400
+ encryptionClient,
401
+ [
402
+ { value: lazyOp.min, column: lazyOp.left, queryType: lazyOp.queryType },
403
+ { value: lazyOp.max, column: lazyOp.left, queryType: lazyOp.queryType }
404
+ ],
405
+ defaultTable,
406
+ tableCache
407
+ );
408
+ return lazyOp.execute(void 0, encryptedMin, encryptedMax);
409
+ }
410
+ const encrypted = await encryptValue(
411
+ encryptionClient,
412
+ lazyOp.right,
413
+ lazyOp.left,
414
+ defaultTable,
415
+ tableCache,
416
+ lazyOp.queryType
417
+ );
418
+ return lazyOp.execute(encrypted);
419
+ }
420
+ function createComparisonOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
421
+ const { config } = columnInfo;
422
+ const requiresOrderAndRange = ["gt", "gte", "lt", "lte"].includes(operator);
423
+ if (requiresOrderAndRange) {
424
+ if (!config?.orderAndRange) {
425
+ switch (operator) {
426
+ case "gt":
427
+ return gt(left, right);
428
+ case "gte":
429
+ return gte(left, right);
430
+ case "lt":
431
+ return lt(left, right);
432
+ case "lte":
433
+ return lte(left, right);
434
+ }
435
+ }
436
+ const executeFn = (encrypted) => {
437
+ if (encrypted === void 0) {
438
+ throw new EncryptionOperatorError(
439
+ `Encryption failed for ${operator} operator`,
440
+ {
441
+ columnName: columnInfo.columnName,
442
+ tableName: columnInfo.tableName,
443
+ operator
444
+ }
445
+ );
446
+ }
447
+ return sql`eql_v2.${sql.raw(operator)}(${left}, ${bindIfParam(encrypted, left)})`;
448
+ };
449
+ return createLazyOperator(
450
+ operator,
451
+ left,
452
+ right,
453
+ executeFn,
454
+ true,
455
+ columnInfo,
456
+ encryptionClient,
457
+ defaultTable,
458
+ tableCache,
459
+ void 0,
460
+ // min
461
+ void 0,
462
+ // max
463
+ queryTypes.orderAndRange
464
+ );
465
+ }
466
+ const requiresEquality = ["eq", "ne"].includes(operator);
467
+ if (requiresEquality && config?.equality) {
468
+ const executeFn = (encrypted) => {
469
+ if (encrypted === void 0) {
470
+ throw new EncryptionOperatorError(
471
+ `Encryption failed for ${operator} operator`,
472
+ {
473
+ columnName: columnInfo.columnName,
474
+ tableName: columnInfo.tableName,
475
+ operator
476
+ }
477
+ );
478
+ }
479
+ return operator === "eq" ? eq(left, encrypted) : ne(left, encrypted);
480
+ };
481
+ return createLazyOperator(
482
+ operator,
483
+ left,
484
+ right,
485
+ executeFn,
486
+ true,
487
+ columnInfo,
488
+ encryptionClient,
489
+ defaultTable,
490
+ tableCache,
491
+ void 0,
492
+ // min
493
+ void 0,
494
+ // max
495
+ queryTypes.equality
496
+ );
497
+ }
498
+ return operator === "eq" ? eq(left, right) : ne(left, right);
499
+ }
500
+ function createRangeOperator(operator, left, min, max, columnInfo, encryptionClient, defaultTable, tableCache) {
501
+ const { config } = columnInfo;
502
+ if (!config?.orderAndRange) {
503
+ return operator === "between" ? between(left, min, max) : notBetween(left, min, max);
504
+ }
505
+ const executeFn = (_encrypted, encryptedMin, encryptedMax) => {
506
+ if (encryptedMin === void 0 || encryptedMax === void 0) {
507
+ throw new EncryptionOperatorError(
508
+ `${operator} operator requires both min and max values`,
509
+ {
510
+ columnName: columnInfo.columnName,
511
+ tableName: columnInfo.tableName,
512
+ operator
513
+ }
514
+ );
515
+ }
516
+ const rangeCondition = sql`eql_v2.gte(${left}, ${bindIfParam(encryptedMin, left)}) AND eql_v2.lte(${left}, ${bindIfParam(encryptedMax, left)})`;
517
+ return operator === "between" ? rangeCondition : sql`NOT (${rangeCondition})`;
518
+ };
519
+ return createLazyOperator(
520
+ operator,
521
+ left,
522
+ void 0,
523
+ executeFn,
524
+ true,
525
+ columnInfo,
526
+ encryptionClient,
527
+ defaultTable,
528
+ tableCache,
529
+ min,
530
+ max,
531
+ queryTypes.orderAndRange
532
+ );
533
+ }
534
+ function createTextSearchOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
535
+ const { config } = columnInfo;
536
+ if (!config?.freeTextSearch) {
537
+ const rightValue = right;
538
+ switch (operator) {
539
+ case "like":
540
+ return like(left, rightValue);
541
+ case "ilike":
542
+ return ilike(left, rightValue);
543
+ case "notIlike":
544
+ return notIlike(left, rightValue);
545
+ }
546
+ }
547
+ const executeFn = (encrypted) => {
548
+ if (encrypted === void 0) {
549
+ throw new EncryptionOperatorError(
550
+ `Encryption failed for ${operator} operator`,
551
+ {
552
+ columnName: columnInfo.columnName,
553
+ tableName: columnInfo.tableName,
554
+ operator
555
+ }
556
+ );
557
+ }
558
+ const sqlFn = sql`eql_v2.${sql.raw(operator === "notIlike" ? "ilike" : operator)}(${left}, ${bindIfParam(encrypted, left)})`;
559
+ return operator === "notIlike" ? sql`NOT (${sqlFn})` : sqlFn;
560
+ };
561
+ return createLazyOperator(
562
+ operator,
563
+ left,
564
+ right,
565
+ executeFn,
566
+ true,
567
+ columnInfo,
568
+ encryptionClient,
569
+ defaultTable,
570
+ tableCache,
571
+ void 0,
572
+ // min
573
+ void 0,
574
+ // max
575
+ queryTypes.freeTextSearch
576
+ );
577
+ }
578
+ function createJsonbOperator(operator, left, right, columnInfo, encryptionClient, defaultTable, tableCache) {
579
+ const { config } = columnInfo;
580
+ const encryptedSelector = (value) => sql`${bindIfParam(value, left)}::eql_v2_encrypted`;
581
+ if (!config?.searchableJson) {
582
+ throw new EncryptionOperatorError(
583
+ `The ${operator} operator requires searchableJson to be enabled on the column configuration.`,
584
+ {
585
+ columnName: columnInfo.columnName,
586
+ tableName: columnInfo.tableName,
587
+ operator
588
+ }
589
+ );
590
+ }
591
+ const executeFn = (encrypted) => {
592
+ if (encrypted === void 0) {
593
+ throw new EncryptionOperatorError(
594
+ `Encryption failed for ${operator} operator`,
595
+ {
596
+ columnName: columnInfo.columnName,
597
+ tableName: columnInfo.tableName,
598
+ operator
599
+ }
600
+ );
601
+ }
602
+ switch (operator) {
603
+ case "jsonbPathQueryFirst":
604
+ return sql`eql_v2.jsonb_path_query_first(${left}, ${encryptedSelector(encrypted)})`;
605
+ case "jsonbGet":
606
+ return sql`${left} -> ${encryptedSelector(encrypted)}`;
607
+ case "jsonbPathExists":
608
+ return sql`eql_v2.jsonb_path_exists(${left}, ${encryptedSelector(encrypted)})`;
609
+ }
610
+ };
611
+ return createLazyOperator(
612
+ operator,
613
+ left,
614
+ right,
615
+ executeFn,
616
+ true,
617
+ columnInfo,
618
+ encryptionClient,
619
+ defaultTable,
620
+ tableCache,
621
+ void 0,
622
+ void 0,
623
+ queryTypes.steVecSelector
624
+ );
625
+ }
626
+ function createEncryptionOperators(encryptionClient) {
627
+ const tableCache = /* @__PURE__ */ new Map();
628
+ const defaultTable = void 0;
629
+ const encryptedEq = (left, right) => {
630
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
631
+ return createComparisonOperator(
632
+ "eq",
633
+ left,
634
+ right,
635
+ columnInfo,
636
+ encryptionClient,
637
+ defaultTable,
638
+ tableCache
639
+ );
640
+ };
641
+ const encryptedNe = (left, right) => {
642
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
643
+ return createComparisonOperator(
644
+ "ne",
645
+ left,
646
+ right,
647
+ columnInfo,
648
+ encryptionClient,
649
+ defaultTable,
650
+ tableCache
651
+ );
652
+ };
653
+ const encryptedGt = (left, right) => {
654
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
655
+ return createComparisonOperator(
656
+ "gt",
657
+ left,
658
+ right,
659
+ columnInfo,
660
+ encryptionClient,
661
+ defaultTable,
662
+ tableCache
663
+ );
664
+ };
665
+ const encryptedGte = (left, right) => {
666
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
667
+ return createComparisonOperator(
668
+ "gte",
669
+ left,
670
+ right,
671
+ columnInfo,
672
+ encryptionClient,
673
+ defaultTable,
674
+ tableCache
675
+ );
676
+ };
677
+ const encryptedLt = (left, right) => {
678
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
679
+ return createComparisonOperator(
680
+ "lt",
681
+ left,
682
+ right,
683
+ columnInfo,
684
+ encryptionClient,
685
+ defaultTable,
686
+ tableCache
687
+ );
688
+ };
689
+ const encryptedLte = (left, right) => {
690
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
691
+ return createComparisonOperator(
692
+ "lte",
693
+ left,
694
+ right,
695
+ columnInfo,
696
+ encryptionClient,
697
+ defaultTable,
698
+ tableCache
699
+ );
700
+ };
701
+ const encryptedBetween = (left, min, max) => {
702
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
703
+ return createRangeOperator(
704
+ "between",
705
+ left,
706
+ min,
707
+ max,
708
+ columnInfo,
709
+ encryptionClient,
710
+ defaultTable,
711
+ tableCache
712
+ );
713
+ };
714
+ const encryptedNotBetween = (left, min, max) => {
715
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
716
+ return createRangeOperator(
717
+ "notBetween",
718
+ left,
719
+ min,
720
+ max,
721
+ columnInfo,
722
+ encryptionClient,
723
+ defaultTable,
724
+ tableCache
725
+ );
726
+ };
727
+ const encryptedLike = (left, right) => {
728
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
729
+ return createTextSearchOperator(
730
+ "like",
731
+ left,
732
+ right,
733
+ columnInfo,
734
+ encryptionClient,
735
+ defaultTable,
736
+ tableCache
737
+ );
738
+ };
739
+ const encryptedIlike = (left, right) => {
740
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
741
+ return createTextSearchOperator(
742
+ "ilike",
743
+ left,
744
+ right,
745
+ columnInfo,
746
+ encryptionClient,
747
+ defaultTable,
748
+ tableCache
749
+ );
750
+ };
751
+ const encryptedNotIlike = (left, right) => {
752
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
753
+ return createTextSearchOperator(
754
+ "notIlike",
755
+ left,
756
+ right,
757
+ columnInfo,
758
+ encryptionClient,
759
+ defaultTable,
760
+ tableCache
761
+ );
762
+ };
763
+ const encryptedJsonbPathQueryFirst = (left, right) => {
764
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
765
+ return createJsonbOperator(
766
+ "jsonbPathQueryFirst",
767
+ left,
768
+ right,
769
+ columnInfo,
770
+ encryptionClient,
771
+ defaultTable,
772
+ tableCache
773
+ );
774
+ };
775
+ const encryptedJsonbGet = (left, right) => {
776
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
777
+ return createJsonbOperator(
778
+ "jsonbGet",
779
+ left,
780
+ right,
781
+ columnInfo,
782
+ encryptionClient,
783
+ defaultTable,
784
+ tableCache
785
+ );
786
+ };
787
+ const encryptedJsonbPathExists = (left, right) => {
788
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
789
+ return createJsonbOperator(
790
+ "jsonbPathExists",
791
+ left,
792
+ right,
793
+ columnInfo,
794
+ encryptionClient,
795
+ defaultTable,
796
+ tableCache
797
+ );
798
+ };
799
+ const encryptedInArray = async (left, right) => {
800
+ if (isSQLWrapper(right)) {
801
+ return inArray(left, right);
802
+ }
803
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
804
+ if (!columnInfo.config?.equality || !Array.isArray(right)) {
805
+ return inArray(left, right);
806
+ }
807
+ const encryptedValues = await encryptValues(
808
+ encryptionClient,
809
+ right.map((value) => ({
810
+ value,
811
+ column: left,
812
+ queryType: queryTypes.equality
813
+ })),
814
+ defaultTable,
815
+ tableCache
816
+ );
817
+ const conditions = encryptedValues.filter((encrypted) => encrypted !== void 0).map((encrypted) => eq(left, encrypted));
818
+ if (conditions.length === 0) {
819
+ return sql`false`;
820
+ }
821
+ const combined = or(...conditions);
822
+ return combined ?? sql`false`;
823
+ };
824
+ const encryptedNotInArray = async (left, right) => {
825
+ if (isSQLWrapper(right)) {
826
+ return notInArray(
827
+ left,
828
+ right
829
+ );
830
+ }
831
+ const columnInfo = getColumnInfo(left, defaultTable, tableCache);
832
+ if (!columnInfo.config?.equality || !Array.isArray(right)) {
833
+ return notInArray(left, right);
834
+ }
835
+ const encryptedValues = await encryptValues(
836
+ encryptionClient,
837
+ right.map((value) => ({
838
+ value,
839
+ column: left,
840
+ queryType: queryTypes.equality
841
+ })),
842
+ defaultTable,
843
+ tableCache
844
+ );
845
+ const conditions = encryptedValues.filter((encrypted) => encrypted !== void 0).map((encrypted) => ne(left, encrypted));
846
+ if (conditions.length === 0) {
847
+ return sql`true`;
848
+ }
849
+ const combined = and(...conditions);
850
+ return combined ?? sql`true`;
851
+ };
852
+ const encryptedAsc = (column) => {
853
+ const columnInfo = getColumnInfo(column, defaultTable, tableCache);
854
+ if (columnInfo.config?.orderAndRange) {
855
+ return asc(sql`eql_v2.order_by(${column})`);
856
+ }
857
+ return asc(column);
858
+ };
859
+ const encryptedDesc = (column) => {
860
+ const columnInfo = getColumnInfo(column, defaultTable, tableCache);
861
+ if (columnInfo.config?.orderAndRange) {
862
+ return desc(sql`eql_v2.order_by(${column})`);
863
+ }
864
+ return desc(column);
865
+ };
866
+ const encryptedAnd = async (...conditions) => {
867
+ const lazyOperators = [];
868
+ const regularConditions = [];
869
+ const regularPromises = [];
870
+ for (const condition of conditions) {
871
+ if (condition === void 0) {
872
+ continue;
873
+ }
874
+ if (isLazyOperator(condition)) {
875
+ lazyOperators.push(condition);
876
+ } else if (condition instanceof Promise) {
877
+ if (isLazyOperator(condition)) {
878
+ lazyOperators.push(condition);
879
+ } else {
880
+ regularPromises.push(condition);
881
+ }
882
+ } else {
883
+ regularConditions.push(condition);
884
+ }
885
+ }
886
+ if (lazyOperators.length === 0) {
887
+ const allConditions2 = [
888
+ ...regularConditions,
889
+ ...await Promise.all(regularPromises)
890
+ ];
891
+ return and(...allConditions2) ?? sql`true`;
892
+ }
893
+ const valuesToEncrypt = [];
894
+ for (let i = 0; i < lazyOperators.length; i++) {
895
+ const lazyOp = lazyOperators[i];
896
+ if (!lazyOp.needsEncryption) {
897
+ continue;
898
+ }
899
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
900
+ valuesToEncrypt.push({
901
+ value: lazyOp.min,
902
+ column: lazyOp.left,
903
+ columnInfo: lazyOp.columnInfo,
904
+ queryType: lazyOp.queryType,
905
+ lazyOpIndex: i,
906
+ isMin: true
907
+ });
908
+ valuesToEncrypt.push({
909
+ value: lazyOp.max,
910
+ column: lazyOp.left,
911
+ columnInfo: lazyOp.columnInfo,
912
+ queryType: lazyOp.queryType,
913
+ lazyOpIndex: i,
914
+ isMax: true
915
+ });
916
+ } else if (lazyOp.right !== void 0) {
917
+ valuesToEncrypt.push({
918
+ value: lazyOp.right,
919
+ column: lazyOp.left,
920
+ columnInfo: lazyOp.columnInfo,
921
+ queryType: lazyOp.queryType,
922
+ lazyOpIndex: i
923
+ });
924
+ }
925
+ }
926
+ const encryptedResults = await encryptValues(
927
+ encryptionClient,
928
+ valuesToEncrypt.map((v) => ({
929
+ value: v.value,
930
+ column: v.column,
931
+ queryType: v.queryType
932
+ })),
933
+ defaultTable,
934
+ tableCache
935
+ );
936
+ const encryptedByLazyOp = /* @__PURE__ */ new Map();
937
+ for (let i = 0; i < valuesToEncrypt.length; i++) {
938
+ const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i];
939
+ const encrypted = encryptedResults[i];
940
+ let group = encryptedByLazyOp.get(lazyOpIndex);
941
+ if (!group) {
942
+ group = {};
943
+ encryptedByLazyOp.set(lazyOpIndex, group);
944
+ }
945
+ if (isMin) {
946
+ group.min = encrypted;
947
+ } else if (isMax) {
948
+ group.max = encrypted;
949
+ } else {
950
+ group.value = encrypted;
951
+ }
952
+ }
953
+ const sqlConditions = [];
954
+ for (let i = 0; i < lazyOperators.length; i++) {
955
+ const lazyOp = lazyOperators[i];
956
+ const encrypted = encryptedByLazyOp.get(i);
957
+ let sqlCondition;
958
+ if (lazyOp.needsEncryption && encrypted) {
959
+ const encryptedValues = [];
960
+ if (encrypted.value !== void 0) {
961
+ encryptedValues.push({
962
+ value: lazyOp.right,
963
+ encrypted: encrypted.value
964
+ });
965
+ }
966
+ if (encrypted.min !== void 0) {
967
+ encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min });
968
+ }
969
+ if (encrypted.max !== void 0) {
970
+ encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max });
971
+ }
972
+ sqlCondition = await executeLazyOperator(lazyOp, encryptedValues);
973
+ } else {
974
+ sqlCondition = lazyOp.execute(lazyOp.right);
975
+ }
976
+ sqlConditions.push(sqlCondition);
977
+ }
978
+ const regularPromisesResults = await Promise.all(regularPromises);
979
+ const allConditions = [
980
+ ...regularConditions,
981
+ ...sqlConditions,
982
+ ...regularPromisesResults
983
+ ];
984
+ return and(...allConditions) ?? sql`true`;
985
+ };
986
+ const encryptedOr = async (...conditions) => {
987
+ const lazyOperators = [];
988
+ const regularConditions = [];
989
+ const regularPromises = [];
990
+ for (const condition of conditions) {
991
+ if (condition === void 0) {
992
+ continue;
993
+ }
994
+ if (isLazyOperator(condition)) {
995
+ lazyOperators.push(condition);
996
+ } else if (condition instanceof Promise) {
997
+ if (isLazyOperator(condition)) {
998
+ lazyOperators.push(condition);
999
+ } else {
1000
+ regularPromises.push(condition);
1001
+ }
1002
+ } else {
1003
+ regularConditions.push(condition);
1004
+ }
1005
+ }
1006
+ if (lazyOperators.length === 0) {
1007
+ const allConditions2 = [
1008
+ ...regularConditions,
1009
+ ...await Promise.all(regularPromises)
1010
+ ];
1011
+ return or(...allConditions2) ?? sql`false`;
1012
+ }
1013
+ const valuesToEncrypt = [];
1014
+ for (let i = 0; i < lazyOperators.length; i++) {
1015
+ const lazyOp = lazyOperators[i];
1016
+ if (!lazyOp.needsEncryption) {
1017
+ continue;
1018
+ }
1019
+ if (lazyOp.min !== void 0 && lazyOp.max !== void 0) {
1020
+ valuesToEncrypt.push({
1021
+ value: lazyOp.min,
1022
+ column: lazyOp.left,
1023
+ columnInfo: lazyOp.columnInfo,
1024
+ queryType: lazyOp.queryType,
1025
+ lazyOpIndex: i,
1026
+ isMin: true
1027
+ });
1028
+ valuesToEncrypt.push({
1029
+ value: lazyOp.max,
1030
+ column: lazyOp.left,
1031
+ columnInfo: lazyOp.columnInfo,
1032
+ queryType: lazyOp.queryType,
1033
+ lazyOpIndex: i,
1034
+ isMax: true
1035
+ });
1036
+ } else if (lazyOp.right !== void 0) {
1037
+ valuesToEncrypt.push({
1038
+ value: lazyOp.right,
1039
+ column: lazyOp.left,
1040
+ columnInfo: lazyOp.columnInfo,
1041
+ queryType: lazyOp.queryType,
1042
+ lazyOpIndex: i
1043
+ });
1044
+ }
1045
+ }
1046
+ const encryptedResults = await encryptValues(
1047
+ encryptionClient,
1048
+ valuesToEncrypt.map((v) => ({
1049
+ value: v.value,
1050
+ column: v.column,
1051
+ queryType: v.queryType
1052
+ })),
1053
+ defaultTable,
1054
+ tableCache
1055
+ );
1056
+ const encryptedByLazyOp = /* @__PURE__ */ new Map();
1057
+ for (let i = 0; i < valuesToEncrypt.length; i++) {
1058
+ const { lazyOpIndex, isMin, isMax } = valuesToEncrypt[i];
1059
+ const encrypted = encryptedResults[i];
1060
+ let group = encryptedByLazyOp.get(lazyOpIndex);
1061
+ if (!group) {
1062
+ group = {};
1063
+ encryptedByLazyOp.set(lazyOpIndex, group);
1064
+ }
1065
+ if (isMin) {
1066
+ group.min = encrypted;
1067
+ } else if (isMax) {
1068
+ group.max = encrypted;
1069
+ } else {
1070
+ group.value = encrypted;
1071
+ }
1072
+ }
1073
+ const sqlConditions = [];
1074
+ for (let i = 0; i < lazyOperators.length; i++) {
1075
+ const lazyOp = lazyOperators[i];
1076
+ const encrypted = encryptedByLazyOp.get(i);
1077
+ let sqlCondition;
1078
+ if (lazyOp.needsEncryption && encrypted) {
1079
+ const encryptedValues = [];
1080
+ if (encrypted.value !== void 0) {
1081
+ encryptedValues.push({
1082
+ value: lazyOp.right,
1083
+ encrypted: encrypted.value
1084
+ });
1085
+ }
1086
+ if (encrypted.min !== void 0) {
1087
+ encryptedValues.push({ value: lazyOp.min, encrypted: encrypted.min });
1088
+ }
1089
+ if (encrypted.max !== void 0) {
1090
+ encryptedValues.push({ value: lazyOp.max, encrypted: encrypted.max });
1091
+ }
1092
+ sqlCondition = await executeLazyOperator(lazyOp, encryptedValues);
1093
+ } else {
1094
+ sqlCondition = lazyOp.execute(lazyOp.right);
1095
+ }
1096
+ sqlConditions.push(sqlCondition);
1097
+ }
1098
+ const regularPromisesResults = await Promise.all(regularPromises);
1099
+ const allConditions = [
1100
+ ...regularConditions,
1101
+ ...sqlConditions,
1102
+ ...regularPromisesResults
1103
+ ];
1104
+ return or(...allConditions) ?? sql`false`;
1105
+ };
1106
+ return {
1107
+ // Comparison operators
1108
+ eq: encryptedEq,
1109
+ ne: encryptedNe,
1110
+ gt: encryptedGt,
1111
+ gte: encryptedGte,
1112
+ lt: encryptedLt,
1113
+ lte: encryptedLte,
1114
+ // Range operators
1115
+ between: encryptedBetween,
1116
+ notBetween: encryptedNotBetween,
1117
+ // Text search operators
1118
+ like: encryptedLike,
1119
+ ilike: encryptedIlike,
1120
+ notIlike: encryptedNotIlike,
1121
+ // Searchable JSON operators
1122
+ jsonbPathQueryFirst: encryptedJsonbPathQueryFirst,
1123
+ jsonbGet: encryptedJsonbGet,
1124
+ jsonbPathExists: encryptedJsonbPathExists,
1125
+ // Array operators
1126
+ inArray: encryptedInArray,
1127
+ notInArray: encryptedNotInArray,
1128
+ // Sorting operators
1129
+ asc: encryptedAsc,
1130
+ desc: encryptedDesc,
1131
+ // AND operator - batches encryption operations
1132
+ and: encryptedAnd,
1133
+ // OR operator - batches encryption operations
1134
+ or: encryptedOr,
1135
+ // Operators that don't need encryption (pass through to Drizzle)
1136
+ exists,
1137
+ notExists,
1138
+ isNull,
1139
+ isNotNull,
1140
+ not,
1141
+ // Array operators that work with arrays directly (not encrypted values)
1142
+ arrayContains,
1143
+ arrayContained,
1144
+ arrayOverlaps
1145
+ };
1146
+ }
1147
+
1148
+ // src/drizzle/index.ts
1149
+ var columnConfigMap = /* @__PURE__ */ new Map();
1150
+ var encryptedType = (name, config) => {
1151
+ const customColumnType = customType({
1152
+ dataType() {
1153
+ return "eql_v2_encrypted";
1154
+ },
1155
+ toDriver(value) {
1156
+ const jsonStr = JSON.stringify(value);
1157
+ const escaped = jsonStr.replace(/"/g, '""');
1158
+ return `("${escaped}")`;
1159
+ },
1160
+ fromDriver(value) {
1161
+ const parseComposite = (str) => {
1162
+ if (!str || str === "") return null;
1163
+ const trimmed = str.trim();
1164
+ if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
1165
+ let inner = trimmed.slice(1, -1);
1166
+ inner = inner.replace(/""/g, '"');
1167
+ if (inner.startsWith('"') && inner.endsWith('"')) {
1168
+ const stripped = inner.slice(1, -1);
1169
+ return JSON.parse(stripped);
1170
+ }
1171
+ if (inner.startsWith("{") || inner.startsWith("[")) {
1172
+ return JSON.parse(inner);
1173
+ }
1174
+ return inner;
1175
+ }
1176
+ return JSON.parse(str);
1177
+ };
1178
+ return parseComposite(value);
1179
+ }
1180
+ });
1181
+ const column = customColumnType(name);
1182
+ const fullConfig = {
1183
+ name,
1184
+ ...config
1185
+ };
1186
+ columnConfigMap.set(name, fullConfig);
1187
+ column._encryptionConfig = fullConfig;
1188
+ return column;
1189
+ };
1190
+ function getEncryptedColumnConfig(columnName, column) {
1191
+ if (column && typeof column === "object") {
1192
+ const columnAny = column;
1193
+ const isEncrypted = columnAny.sqlName === "eql_v2_encrypted" || columnAny.dataType === "eql_v2_encrypted" || columnAny.dataType && typeof columnAny.dataType === "function" && columnAny.dataType() === "eql_v2_encrypted";
1194
+ if (isEncrypted) {
1195
+ if (columnAny._encryptionConfig) {
1196
+ return columnAny._encryptionConfig;
1197
+ }
1198
+ const lookupName = columnAny.name || columnName;
1199
+ return columnConfigMap.get(lookupName);
1200
+ }
1201
+ }
1202
+ return void 0;
1203
+ }
1204
+ export {
1205
+ EncryptionConfigError,
1206
+ EncryptionOperatorError,
1207
+ createEncryptionOperators,
1208
+ encryptedType,
1209
+ extractEncryptionSchema,
1210
+ getEncryptedColumnConfig
1211
+ };
1212
+ //# sourceMappingURL=index.js.map