@cipherstash/stack 0.16.0 → 0.18.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 (64) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/{chunk-6FD7OBGM.js → chunk-LLCCNKDL.js} +3 -3
  3. package/dist/chunk-LLCCNKDL.js.map +1 -0
  4. package/dist/{chunk-MD6742R6.js → chunk-VPOTNP4K.js} +1 -1
  5. package/dist/chunk-VPOTNP4K.js.map +1 -0
  6. package/dist/{chunk-4RNBI3UH.js → chunk-XWPGAHBZ.js} +1 -1
  7. package/dist/chunk-XWPGAHBZ.js.map +1 -0
  8. package/dist/{chunk-JDZ2QUUF.js → chunk-YWQXTZ5M.js} +4 -2
  9. package/dist/{chunk-JDZ2QUUF.js.map → chunk-YWQXTZ5M.js.map} +1 -1
  10. package/dist/{chunk-CY5B4LIF.js → chunk-ZYOZHZMJ.js} +160 -52
  11. package/dist/chunk-ZYOZHZMJ.js.map +1 -0
  12. package/dist/{client-BLbA6aFD.d.ts → client-CIsfZ2zg.d.ts} +17 -22
  13. package/dist/{client-C_7TF8EL.d.cts → client-Dt98Rugc.d.cts} +17 -22
  14. package/dist/client.cjs +2 -0
  15. package/dist/client.cjs.map +1 -1
  16. package/dist/client.d.cts +2 -2
  17. package/dist/client.d.ts +2 -2
  18. package/dist/client.js +1 -1
  19. package/dist/drizzle/index.cjs +6 -3
  20. package/dist/drizzle/index.cjs.map +1 -1
  21. package/dist/drizzle/index.d.cts +2 -2
  22. package/dist/drizzle/index.d.ts +2 -2
  23. package/dist/drizzle/index.js +6 -5
  24. package/dist/drizzle/index.js.map +1 -1
  25. package/dist/dynamodb/index.cjs +14 -4
  26. package/dist/dynamodb/index.cjs.map +1 -1
  27. package/dist/dynamodb/index.d.cts +12 -12
  28. package/dist/dynamodb/index.d.ts +12 -12
  29. package/dist/dynamodb/index.js +9 -3
  30. package/dist/dynamodb/index.js.map +1 -1
  31. package/dist/encryption/index.cjs +168 -50
  32. package/dist/encryption/index.cjs.map +1 -1
  33. package/dist/encryption/index.d.cts +2 -2
  34. package/dist/encryption/index.d.ts +2 -2
  35. package/dist/encryption/index.js +25 -5
  36. package/dist/identity/index.cjs +2 -2
  37. package/dist/identity/index.cjs.map +1 -1
  38. package/dist/identity/index.js +3 -3
  39. package/dist/index.cjs +150 -50
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +3 -3
  42. package/dist/index.d.ts +3 -3
  43. package/dist/index.js +5 -5
  44. package/dist/schema/index.cjs +3 -1
  45. package/dist/schema/index.cjs.map +1 -1
  46. package/dist/schema/index.d.cts +1 -1
  47. package/dist/schema/index.d.ts +1 -1
  48. package/dist/schema/index.js +1 -1
  49. package/dist/supabase/index.cjs +2 -2
  50. package/dist/supabase/index.cjs.map +1 -1
  51. package/dist/supabase/index.d.cts +2 -2
  52. package/dist/supabase/index.d.ts +2 -2
  53. package/dist/supabase/index.js +3 -3
  54. package/dist/{types-public-Dv-r6Ik0.d.ts → types-public-BTxqjmtv.d.cts} +95 -80
  55. package/dist/{types-public-Dv-r6Ik0.d.cts → types-public-BTxqjmtv.d.ts} +95 -80
  56. package/dist/types-public.cjs.map +1 -1
  57. package/dist/types-public.d.cts +1 -1
  58. package/dist/types-public.d.ts +1 -1
  59. package/dist/types-public.js +1 -1
  60. package/package.json +12 -12
  61. package/dist/chunk-4RNBI3UH.js.map +0 -1
  62. package/dist/chunk-6FD7OBGM.js.map +0 -1
  63. package/dist/chunk-CY5B4LIF.js.map +0 -1
  64. package/dist/chunk-MD6742R6.js.map +0 -1
@@ -20,6 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/encryption/index.ts
21
21
  var encryption_exports = {};
22
22
  __export(encryption_exports, {
23
+ BatchEncryptQueryOperation: () => BatchEncryptQueryOperation,
24
+ BulkDecryptModelsOperation: () => BulkDecryptModelsOperation,
25
+ BulkDecryptOperation: () => BulkDecryptOperation,
26
+ BulkEncryptModelsOperation: () => BulkEncryptModelsOperation,
27
+ BulkEncryptOperation: () => BulkEncryptOperation,
28
+ DecryptModelOperation: () => DecryptModelOperation,
29
+ DecryptOperation: () => DecryptOperation,
30
+ EncryptModelOperation: () => EncryptModelOperation,
31
+ EncryptOperation: () => EncryptOperation,
32
+ EncryptQueryOperation: () => EncryptQueryOperation,
23
33
  Encryption: () => Encryption,
24
34
  EncryptionClient: () => EncryptionClient,
25
35
  noClientError: () => noClientError
@@ -103,7 +113,7 @@ var encryptConfigSchema = import_zod.z.object({
103
113
  });
104
114
  function buildEncryptConfig(...protectTables) {
105
115
  const config = {
106
- v: 2,
116
+ v: 1,
107
117
  tables: {}
108
118
  };
109
119
  for (const tb of protectTables) {
@@ -113,7 +123,7 @@ function buildEncryptConfig(...protectTables) {
113
123
  return config;
114
124
  }
115
125
 
116
- // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/utils.mjs
126
+ // ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.10_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/utils.mjs
117
127
  function formatDuration(ms) {
118
128
  if (ms < 1e3) return `${Math.round(ms)}ms`;
119
129
  return `${(ms / 1e3).toFixed(2)}s`;
@@ -169,7 +179,7 @@ function matchesPattern(path, pattern) {
169
179
  return new RegExp(`^${regexPattern}$`).test(path);
170
180
  }
171
181
 
172
- // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/logger.mjs
182
+ // ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.10_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/logger.mjs
173
183
  function isPlainObject(val) {
174
184
  return val !== null && typeof val === "object" && !Array.isArray(val);
175
185
  }
@@ -673,6 +683,15 @@ var EncryptionOperation = class {
673
683
  };
674
684
 
675
685
  // src/encryption/operations/batch-encrypt-query.ts
686
+ function filterNullTerms(terms) {
687
+ const nonNullTerms = [];
688
+ terms.forEach((term, index) => {
689
+ if (term.value !== null && term.value !== void 0) {
690
+ nonNullTerms.push({ term, originalIndex: index });
691
+ }
692
+ });
693
+ return { nonNullTerms };
694
+ }
676
695
  function buildQueryPayload(term, lockContext) {
677
696
  assertValidNumericValue(term.value);
678
697
  const { indexType, queryOp } = resolveIndexType(
@@ -693,10 +712,15 @@ function buildQueryPayload(term, lockContext) {
693
712
  }
694
713
  return payload;
695
714
  }
696
- function assembleResults(terms, encryptedValues) {
697
- return terms.map(
698
- (term, i) => formatEncryptedResult(encryptedValues[i], term.returnType)
699
- );
715
+ function assembleResults(totalLength, encryptedValues, nonNullTerms) {
716
+ const results = new Array(totalLength).fill(null);
717
+ nonNullTerms.forEach(({ term, originalIndex }, i) => {
718
+ results[originalIndex] = formatEncryptedResult(
719
+ encryptedValues[i],
720
+ term.returnType
721
+ );
722
+ });
723
+ return results;
700
724
  }
701
725
  var BatchEncryptQueryOperation = class extends EncryptionOperation {
702
726
  constructor(client, terms) {
@@ -704,6 +728,8 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
704
728
  this.client = client;
705
729
  this.terms = terms;
706
730
  }
731
+ client;
732
+ terms;
707
733
  withLockContext(lockContext) {
708
734
  return new BatchEncryptQueryOperationWithLockContext(
709
735
  this.client,
@@ -723,18 +749,23 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
723
749
  log.emit();
724
750
  return { data: [] };
725
751
  }
752
+ const { nonNullTerms } = filterNullTerms(this.terms);
753
+ if (nonNullTerms.length === 0) {
754
+ log.emit();
755
+ return { data: this.terms.map(() => null) };
756
+ }
726
757
  const result = await (0, import_result.withResult)(
727
758
  async () => {
728
759
  if (!this.client) throw noClientError();
729
760
  const { metadata } = this.getAuditData();
730
- const queries = this.terms.map(
731
- (term) => buildQueryPayload(term)
761
+ const queries = nonNullTerms.map(
762
+ ({ term }) => buildQueryPayload(term)
732
763
  );
733
764
  const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
734
765
  queries,
735
766
  unverifiedContext: metadata
736
767
  });
737
- return assembleResults(this.terms, encrypted);
768
+ return assembleResults(this.terms.length, encrypted, nonNullTerms);
738
769
  },
739
770
  (error) => {
740
771
  log.set({ errorCode: getErrorCode(error) ?? "unknown" });
@@ -757,6 +788,9 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
757
788
  this.lockContext = lockContext;
758
789
  this.auditMetadata = auditMetadata;
759
790
  }
791
+ client;
792
+ terms;
793
+ lockContext;
760
794
  async execute() {
761
795
  const log = createRequestLogger();
762
796
  log.set({
@@ -768,6 +802,11 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
768
802
  log.emit();
769
803
  return { data: [] };
770
804
  }
805
+ const { nonNullTerms } = filterNullTerms(this.terms);
806
+ if (nonNullTerms.length === 0) {
807
+ log.emit();
808
+ return { data: this.terms.map(() => null) };
809
+ }
771
810
  const lockContextResult = await this.lockContext.getLockContext();
772
811
  if (lockContextResult.failure) {
773
812
  log.emit();
@@ -778,15 +817,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
778
817
  async () => {
779
818
  if (!this.client) throw noClientError();
780
819
  const { metadata } = this.getAuditData();
781
- const queries = this.terms.map(
782
- (term) => buildQueryPayload(term, context)
820
+ const queries = nonNullTerms.map(
821
+ ({ term }) => buildQueryPayload(term, context)
783
822
  );
784
823
  const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
785
824
  queries,
786
825
  serviceToken: ctsToken,
787
826
  unverifiedContext: metadata
788
827
  });
789
- return assembleResults(this.terms, encrypted);
828
+ return assembleResults(this.terms.length, encrypted, nonNullTerms);
790
829
  },
791
830
  (error) => {
792
831
  log.set({ errorCode: getErrorCode(error) ?? "unknown" });
@@ -806,25 +845,30 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
806
845
  var import_result2 = require("@byteslice/result");
807
846
  var import_protect_ffi3 = require("@cipherstash/protect-ffi");
808
847
  var createDecryptPayloads = (encryptedPayloads, lockContext) => {
809
- return encryptedPayloads.map(({ id, data }) => ({
848
+ return encryptedPayloads.filter(({ data }) => data !== null).map(({ id, data }) => ({
810
849
  id,
811
850
  ciphertext: data,
812
851
  ...lockContext && { lockContext }
813
852
  }));
814
853
  };
854
+ var createNullResult = (encryptedPayloads) => encryptedPayloads.map(({ id }) => ({ id, data: null }));
815
855
  var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
816
- return decryptedData.map((decryptResult, i) => {
817
- if ("error" in decryptResult) {
818
- return {
819
- id: encryptedPayloads[i].id,
820
- error: decryptResult.error
821
- };
856
+ const result = new Array(encryptedPayloads.length);
857
+ let decryptedIndex = 0;
858
+ for (let i = 0; i < encryptedPayloads.length; i++) {
859
+ if (encryptedPayloads[i].data === null) {
860
+ result[i] = { id: encryptedPayloads[i].id, data: null };
861
+ } else {
862
+ const decryptResult = decryptedData[decryptedIndex];
863
+ if ("error" in decryptResult) {
864
+ result[i] = { id: encryptedPayloads[i].id, error: decryptResult.error };
865
+ } else {
866
+ result[i] = { id: encryptedPayloads[i].id, data: decryptResult.data };
867
+ }
868
+ decryptedIndex++;
822
869
  }
823
- return {
824
- id: encryptedPayloads[i].id,
825
- data: decryptResult.data
826
- };
827
- });
870
+ }
871
+ return result;
828
872
  };
829
873
  var BulkDecryptOperation = class extends EncryptionOperation {
830
874
  client;
@@ -849,10 +893,13 @@ var BulkDecryptOperation = class extends EncryptionOperation {
849
893
  if (!this.client) throw noClientError();
850
894
  if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
851
895
  return [];
852
- const payloads = createDecryptPayloads(this.encryptedPayloads);
896
+ const nonNullPayloads = createDecryptPayloads(this.encryptedPayloads);
897
+ if (nonNullPayloads.length === 0) {
898
+ return createNullResult(this.encryptedPayloads);
899
+ }
853
900
  const { metadata } = this.getAuditData();
854
901
  const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(this.client, {
855
- ciphertexts: payloads,
902
+ ciphertexts: nonNullPayloads,
856
903
  unverifiedContext: metadata
857
904
  });
858
905
  return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
@@ -904,13 +951,16 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
904
951
  if (context.failure) {
905
952
  throw new Error(`[encryption]: ${context.failure.message}`);
906
953
  }
907
- const payloads = createDecryptPayloads(
954
+ const nonNullPayloads = createDecryptPayloads(
908
955
  encryptedPayloads,
909
956
  context.data.context
910
957
  );
958
+ if (nonNullPayloads.length === 0) {
959
+ return createNullResult(encryptedPayloads);
960
+ }
911
961
  const { metadata } = this.getAuditData();
912
962
  const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(client, {
913
- ciphertexts: payloads,
963
+ ciphertexts: nonNullPayloads,
914
964
  serviceToken: context.data.ctsToken,
915
965
  unverifiedContext: metadata
916
966
  });
@@ -1549,7 +1599,7 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
1549
1599
  var import_result4 = require("@byteslice/result");
1550
1600
  var import_protect_ffi5 = require("@cipherstash/protect-ffi");
1551
1601
  var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
1552
- return plaintexts.map(({ id, plaintext }) => ({
1602
+ return plaintexts.filter(({ plaintext }) => plaintext !== null).map(({ id, plaintext }) => ({
1553
1603
  id,
1554
1604
  plaintext,
1555
1605
  column: column.getName(),
@@ -1557,6 +1607,20 @@ var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
1557
1607
  ...lockContext && { lockContext }
1558
1608
  }));
1559
1609
  };
1610
+ var createNullResult2 = (plaintexts) => plaintexts.map(({ id }) => ({ id, data: null }));
1611
+ var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
1612
+ const result = new Array(plaintexts.length);
1613
+ let encryptedIndex = 0;
1614
+ for (let i = 0; i < plaintexts.length; i++) {
1615
+ if (plaintexts[i].plaintext === null) {
1616
+ result[i] = { id: plaintexts[i].id, data: null };
1617
+ } else {
1618
+ result[i] = { id: plaintexts[i].id, data: encryptedData[encryptedIndex] };
1619
+ encryptedIndex++;
1620
+ }
1621
+ }
1622
+ return result;
1623
+ };
1560
1624
  var BulkEncryptOperation = class extends EncryptionOperation {
1561
1625
  client;
1562
1626
  plaintexts;
@@ -1589,20 +1653,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
1589
1653
  if (!this.plaintexts || this.plaintexts.length === 0) {
1590
1654
  return [];
1591
1655
  }
1592
- const payloads = createEncryptPayloads(
1656
+ const nonNullPayloads = createEncryptPayloads(
1593
1657
  this.plaintexts,
1594
1658
  this.column,
1595
1659
  this.table
1596
1660
  );
1661
+ if (nonNullPayloads.length === 0) {
1662
+ return createNullResult2(this.plaintexts);
1663
+ }
1597
1664
  const { metadata } = this.getAuditData();
1598
1665
  const encryptedData = await (0, import_protect_ffi5.encryptBulk)(this.client, {
1599
- plaintexts: payloads,
1666
+ plaintexts: nonNullPayloads,
1600
1667
  unverifiedContext: metadata
1601
1668
  });
1602
- return encryptedData.map((data, i) => ({
1603
- id: this.plaintexts[i].id,
1604
- data
1605
- }));
1669
+ return mapEncryptedDataToResult(this.plaintexts, encryptedData);
1606
1670
  },
1607
1671
  (error) => {
1608
1672
  log.set({ errorCode: getErrorCode(error) ?? "unknown" });
@@ -1659,22 +1723,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
1659
1723
  if (context.failure) {
1660
1724
  throw new Error(`[encryption]: ${context.failure.message}`);
1661
1725
  }
1662
- const payloads = createEncryptPayloads(
1726
+ const nonNullPayloads = createEncryptPayloads(
1663
1727
  plaintexts,
1664
1728
  column,
1665
1729
  table,
1666
1730
  context.data.context
1667
1731
  );
1732
+ if (nonNullPayloads.length === 0) {
1733
+ return createNullResult2(plaintexts);
1734
+ }
1668
1735
  const { metadata } = this.getAuditData();
1669
1736
  const encryptedData = await (0, import_protect_ffi5.encryptBulk)(client, {
1670
- plaintexts: payloads,
1737
+ plaintexts: nonNullPayloads,
1671
1738
  serviceToken: context.data.ctsToken,
1672
1739
  unverifiedContext: metadata
1673
1740
  });
1674
- return encryptedData.map((data, i) => ({
1675
- id: plaintexts[i].id,
1676
- data
1677
- }));
1741
+ return mapEncryptedDataToResult(plaintexts, encryptedData);
1678
1742
  },
1679
1743
  (error) => {
1680
1744
  log.set({ errorCode: getErrorCode(error) ?? "unknown" });
@@ -1804,6 +1868,10 @@ var import_result6 = require("@byteslice/result");
1804
1868
  var import_protect_ffi6 = require("@cipherstash/protect-ffi");
1805
1869
  var DecryptOperation = class extends EncryptionOperation {
1806
1870
  client;
1871
+ // Internally widened to allow null so the runtime guard below can
1872
+ // short-circuit on legacy / manually-NULLed rows. The public
1873
+ // `Encryption.decrypt()` signature still rejects null at the type
1874
+ // layer; this is defense in depth for direct construction.
1807
1875
  encryptedData;
1808
1876
  constructor(client, encryptedData) {
1809
1877
  super();
@@ -1824,6 +1892,9 @@ var DecryptOperation = class extends EncryptionOperation {
1824
1892
  if (!this.client) {
1825
1893
  throw noClientError();
1826
1894
  }
1895
+ if (this.encryptedData === null) {
1896
+ return null;
1897
+ }
1827
1898
  const { metadata } = this.getAuditData();
1828
1899
  return await (0, import_protect_ffi6.decrypt)(this.client, {
1829
1900
  ciphertext: this.encryptedData,
@@ -1874,6 +1945,9 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
1874
1945
  if (!client) {
1875
1946
  throw noClientError();
1876
1947
  }
1948
+ if (encryptedData === null) {
1949
+ return null;
1950
+ }
1877
1951
  const { metadata } = this.getAuditData();
1878
1952
  const context = await this.lockContext.getLockContext();
1879
1953
  if (context.failure) {
@@ -2001,6 +2075,10 @@ var import_result8 = require("@byteslice/result");
2001
2075
  var import_protect_ffi7 = require("@cipherstash/protect-ffi");
2002
2076
  var EncryptOperation = class extends EncryptionOperation {
2003
2077
  client;
2078
+ // Internally widened to allow null so the runtime guard below can
2079
+ // short-circuit. The public `Encryption.encrypt()` signature still
2080
+ // rejects null at the type layer; this is defense in depth for callers
2081
+ // that reach this class through casts or dynamic field walking.
2004
2082
  plaintext;
2005
2083
  column;
2006
2084
  table;
@@ -2027,6 +2105,9 @@ var EncryptOperation = class extends EncryptionOperation {
2027
2105
  if (!this.client) {
2028
2106
  throw noClientError();
2029
2107
  }
2108
+ if (this.plaintext === null) {
2109
+ return null;
2110
+ }
2030
2111
  if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
2031
2112
  throw new Error("[encryption]: Cannot encrypt NaN value");
2032
2113
  }
@@ -2088,6 +2169,9 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
2088
2169
  if (!client) {
2089
2170
  throw noClientError();
2090
2171
  }
2172
+ if (plaintext === null) {
2173
+ return null;
2174
+ }
2091
2175
  const { metadata } = this.getAuditData();
2092
2176
  const context = await this.lockContext.getLockContext();
2093
2177
  if (context.failure) {
@@ -2233,6 +2317,9 @@ var EncryptQueryOperation = class extends EncryptionOperation {
2233
2317
  this.plaintext = plaintext;
2234
2318
  this.opts = opts;
2235
2319
  }
2320
+ client;
2321
+ plaintext;
2322
+ opts;
2236
2323
  withLockContext(lockContext) {
2237
2324
  return new EncryptQueryOperationWithLockContext(
2238
2325
  this.client,
@@ -2251,7 +2338,12 @@ var EncryptQueryOperation = class extends EncryptionOperation {
2251
2338
  queryType: this.opts.queryType,
2252
2339
  lockContext: false
2253
2340
  });
2254
- const validationError = validateNumericValue(this.plaintext);
2341
+ if (this.plaintext === null || this.plaintext === void 0) {
2342
+ log.emit();
2343
+ return { data: null };
2344
+ }
2345
+ const plaintext = this.plaintext;
2346
+ const validationError = validateNumericValue(plaintext);
2255
2347
  if (validationError?.failure) {
2256
2348
  log.emit();
2257
2349
  return { failure: validationError.failure };
@@ -2263,15 +2355,15 @@ var EncryptQueryOperation = class extends EncryptionOperation {
2263
2355
  const { indexType, queryOp } = resolveIndexType(
2264
2356
  this.opts.column,
2265
2357
  this.opts.queryType,
2266
- this.plaintext
2358
+ plaintext
2267
2359
  );
2268
2360
  assertValueIndexCompatibility(
2269
- this.plaintext,
2361
+ plaintext,
2270
2362
  indexType,
2271
2363
  this.opts.column.getName()
2272
2364
  );
2273
2365
  const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
2274
- plaintext: this.plaintext,
2366
+ plaintext,
2275
2367
  column: this.opts.column.getName(),
2276
2368
  table: this.opts.table.tableName,
2277
2369
  indexType,
@@ -2305,6 +2397,10 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
2305
2397
  this.lockContext = lockContext;
2306
2398
  this.auditMetadata = auditMetadata;
2307
2399
  }
2400
+ client;
2401
+ plaintext;
2402
+ opts;
2403
+ lockContext;
2308
2404
  async execute() {
2309
2405
  const log = createRequestLogger();
2310
2406
  log.set({
@@ -2314,7 +2410,12 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
2314
2410
  queryType: this.opts.queryType,
2315
2411
  lockContext: true
2316
2412
  });
2317
- const validationError = validateNumericValue(this.plaintext);
2413
+ if (this.plaintext === null || this.plaintext === void 0) {
2414
+ log.emit();
2415
+ return { data: null };
2416
+ }
2417
+ const plaintext = this.plaintext;
2418
+ const validationError = validateNumericValue(plaintext);
2318
2419
  if (validationError?.failure) {
2319
2420
  log.emit();
2320
2421
  return { failure: validationError.failure };
@@ -2332,15 +2433,15 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
2332
2433
  const { indexType, queryOp } = resolveIndexType(
2333
2434
  this.opts.column,
2334
2435
  this.opts.queryType,
2335
- this.plaintext
2436
+ plaintext
2336
2437
  );
2337
2438
  assertValueIndexCompatibility(
2338
- this.plaintext,
2439
+ plaintext,
2339
2440
  indexType,
2340
2441
  this.opts.column.getName()
2341
2442
  );
2342
2443
  const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
2343
- plaintext: this.plaintext,
2444
+ plaintext,
2344
2445
  column: this.opts.column.getName(),
2345
2446
  table: this.opts.table.tableName,
2346
2447
  indexType,
@@ -2536,6 +2637,13 @@ var EncryptionClient = class {
2536
2637
  * .withLockContext(lockContext)
2537
2638
  * ```
2538
2639
  *
2640
+ * @remarks
2641
+ * The public input type rejects null, but at runtime `decrypt` will
2642
+ * short-circuit and return null when given a null ciphertext
2643
+ * (defense in depth for legacy / manually-NULLed DB rows reached via
2644
+ * casts or dynamic field walking). The narrow return type holds for
2645
+ * any caller that respects the input contract.
2646
+ *
2539
2647
  * @see {@link LockContext}
2540
2648
  * @see {@link DecryptOperation}
2541
2649
  */
@@ -2815,6 +2923,16 @@ var Encryption = async (config) => {
2815
2923
  };
2816
2924
  // Annotate the CommonJS export names for ESM import in node:
2817
2925
  0 && (module.exports = {
2926
+ BatchEncryptQueryOperation,
2927
+ BulkDecryptModelsOperation,
2928
+ BulkDecryptOperation,
2929
+ BulkEncryptModelsOperation,
2930
+ BulkEncryptOperation,
2931
+ DecryptModelOperation,
2932
+ DecryptOperation,
2933
+ EncryptModelOperation,
2934
+ EncryptOperation,
2935
+ EncryptQueryOperation,
2818
2936
  Encryption,
2819
2937
  EncryptionClient,
2820
2938
  noClientError