@cipherstash/stack 0.19.0 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +531 -0
  2. package/README.md +95 -77
  3. package/dist/adapter-kit.cjs +923 -0
  4. package/dist/adapter-kit.cjs.map +1 -0
  5. package/dist/adapter-kit.d.cts +82 -0
  6. package/dist/adapter-kit.d.ts +82 -0
  7. package/dist/adapter-kit.js +47 -0
  8. package/dist/adapter-kit.js.map +1 -0
  9. package/dist/base-operation-AOAIvsSB.d.cts +32 -0
  10. package/dist/base-operation-FXEzUXIq.d.ts +32 -0
  11. package/dist/{chunk-4AVL4VZD.js → chunk-3B5ZX3IS.js} +3 -1
  12. package/dist/chunk-3B5ZX3IS.js.map +1 -0
  13. package/dist/chunk-7333ZC6L.js +48 -0
  14. package/dist/chunk-7333ZC6L.js.map +1 -0
  15. package/dist/{chunk-MP3SSDNN.js → chunk-CLM7E4I6.js} +15 -15
  16. package/dist/{chunk-MP3SSDNN.js.map → chunk-CLM7E4I6.js.map} +1 -1
  17. package/dist/{chunk-U66S7VIF.js → chunk-V2Q3NYIH.js} +166 -107
  18. package/dist/chunk-V2Q3NYIH.js.map +1 -0
  19. package/dist/chunk-X3JRXEIB.js +98 -0
  20. package/dist/chunk-X3JRXEIB.js.map +1 -0
  21. package/dist/{chunk-36AA7IBJ.js → chunk-ZTP5QJ27.js} +51 -18
  22. package/dist/chunk-ZTP5QJ27.js.map +1 -0
  23. package/dist/client.cjs +29 -12
  24. package/dist/client.cjs.map +1 -1
  25. package/dist/client.d.cts +3 -2
  26. package/dist/client.d.ts +3 -2
  27. package/dist/client.js +2 -2
  28. package/dist/{table-DihEAlxG.d.cts → columns-D2_YzrCX.d.cts} +155 -136
  29. package/dist/{table-CIH7jZ2h.d.ts → columns-rZc7fQHI.d.ts} +155 -136
  30. package/dist/dynamodb/index.d.cts +3 -2
  31. package/dist/dynamodb/index.d.ts +3 -2
  32. package/dist/encryption/index.cjs +54 -16
  33. package/dist/encryption/index.cjs.map +1 -1
  34. package/dist/encryption/index.d.cts +807 -6
  35. package/dist/encryption/index.d.ts +807 -6
  36. package/dist/encryption/index.js +4 -4
  37. package/dist/encryption/v3.cjs +1078 -973
  38. package/dist/encryption/v3.cjs.map +1 -1
  39. package/dist/encryption/v3.d.cts +15 -12
  40. package/dist/encryption/v3.d.ts +15 -12
  41. package/dist/encryption/v3.js +49 -21
  42. package/dist/encryption/v3.js.map +1 -1
  43. package/dist/eql/v3/index.cjs +130 -79
  44. package/dist/eql/v3/index.cjs.map +1 -1
  45. package/dist/eql/v3/index.d.cts +115 -13
  46. package/dist/eql/v3/index.d.ts +115 -13
  47. package/dist/eql/v3/index.js +16 -6
  48. package/dist/index-BquA71_Y.d.ts +24 -0
  49. package/dist/index-fhWTOV0K.d.cts +24 -0
  50. package/dist/index.cjs +79 -27
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +5 -17
  53. package/dist/index.d.ts +5 -17
  54. package/dist/index.js +4 -4
  55. package/dist/schema/index.cjs +29 -12
  56. package/dist/schema/index.cjs.map +1 -1
  57. package/dist/schema/index.d.cts +1 -1
  58. package/dist/schema/index.d.ts +1 -1
  59. package/dist/schema/index.js +2 -2
  60. package/dist/{types-public-CpS5KjwX.d.ts → types-public-QMjYNfQO.d.cts} +765 -726
  61. package/dist/{types-public-CpS5KjwX.d.cts → types-public-QMjYNfQO.d.ts} +765 -726
  62. package/dist/types-public.cjs.map +1 -1
  63. package/dist/types-public.d.cts +1 -1
  64. package/dist/types-public.d.ts +1 -1
  65. package/dist/types-public.js +1 -1
  66. package/dist/wasm-inline.d.ts +779 -405
  67. package/dist/wasm-inline.js +606 -299
  68. package/dist/wasm-inline.js.map +1 -1
  69. package/package.json +25 -53
  70. package/dist/chunk-36AA7IBJ.js.map +0 -1
  71. package/dist/chunk-4AVL4VZD.js.map +0 -1
  72. package/dist/chunk-IADZCZEA.js +0 -23
  73. package/dist/chunk-IADZCZEA.js.map +0 -1
  74. package/dist/chunk-IBSK6P33.js +0 -209
  75. package/dist/chunk-IBSK6P33.js.map +0 -1
  76. package/dist/chunk-U66S7VIF.js.map +0 -1
  77. package/dist/client-DSGHBN-g.d.cts +0 -834
  78. package/dist/client-DfCrlHXh.d.ts +0 -834
  79. package/dist/drizzle/index.cjs +0 -5617
  80. package/dist/drizzle/index.cjs.map +0 -1
  81. package/dist/drizzle/index.d.cts +0 -358
  82. package/dist/drizzle/index.d.ts +0 -358
  83. package/dist/drizzle/index.js +0 -1220
  84. package/dist/drizzle/index.js.map +0 -1
  85. package/dist/supabase/index.cjs +0 -5951
  86. package/dist/supabase/index.cjs.map +0 -1
  87. package/dist/supabase/index.d.cts +0 -223
  88. package/dist/supabase/index.d.ts +0 -223
  89. package/dist/supabase/index.js +0 -1217
  90. package/dist/supabase/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema/match-defaults.ts"],"sourcesContent":["import type { MatchIndexOpts } from './index'\n\n/**\n * Fully-resolved match-index options: every field present and non-`undefined`.\n *\n * `MatchIndexOpts` (the user-facing tuning input) has all fields optional —\n * each is `.default(...).optional()` in the zod schema, so its inferred type is\n * `T | undefined`. This type pins the BUILT/resolved shape explicitly via\n * `NonNullable<...>`, which states the non-null intent directly and is robust\n * regardless of `Required<>`'s subtle, `exactOptionalPropertyTypes`-dependent\n * stripping semantics.\n */\nexport type BuiltMatchIndexOpts = {\n tokenizer: NonNullable<MatchIndexOpts['tokenizer']>\n token_filters: NonNullable<MatchIndexOpts['token_filters']>\n k: NonNullable<MatchIndexOpts['k']>\n m: NonNullable<MatchIndexOpts['m']>\n include_original: NonNullable<MatchIndexOpts['include_original']>\n}\n\n/**\n * Default match-index parameters — the single source of truth shared by the\n * v2 `freeTextSearch()` builder and the v3 domain builders.\n *\n * `include_original: true` is the v2 builder's historical default rather than\n * the zod-schema default of `false`. It is INERT: protect-ffi accepts the flag\n * and ignores it (measured across 0.24 and 0.29, EQL v2 and v3 — the emitted\n * bloom is trigram-only either way). It is kept here only so the v2 emitted\n * config does not move. The v3 domain builders override it to `false`, the\n * value a substring-search domain wants if ffi ever starts honouring it.\n *\n * In particular it does NOT let a value shorter than the tokenizer's\n * `token_length` be matched: such a value blooms to nothing under either\n * setting, which is exactly the fail-open {@link matchNeedleError} guards.\n *\n * This is a FACTORY (not a shared `const`) so every caller gets fresh, unaliased\n * nested objects (`tokenizer`, `token_filters` and the `{ kind: 'downcase' }`\n * inside it). A shared const would be shallow-copied by `{ ...DEFAULT }`, leaving\n * those nested objects aliased across every column — a caller mutating one built\n * config could then corrupt the defaults used by later columns.\n */\nexport function defaultMatchOpts(): BuiltMatchIndexOpts {\n return {\n tokenizer: { kind: 'ngram', token_length: 3 },\n token_filters: [{ kind: 'downcase' }],\n k: 6,\n m: 2048,\n include_original: true,\n }\n}\n\n/**\n * Deep-clone a built match block (`tokenizer` and `token_filters` are its only\n * nested values) so no emitted config or stored builder state ever aliases\n * another's nested objects — a caller mutating one cannot corrupt the other.\n */\nexport function cloneMatchOpts(opts: BuiltMatchIndexOpts): BuiltMatchIndexOpts {\n return {\n ...opts,\n tokenizer: { ...opts.tokenizer },\n token_filters: opts.token_filters.map((f) => ({ ...f })),\n }\n}\n\n/**\n * Resolve user-supplied `freeTextSearch(opts)` input into a fully-built match\n * block: each provided key replaces its default, omitted keys keep the default\n * (`opts?.x ?? default.x`). The single source of truth for that five-field merge\n * shared by the v2 `freeTextSearch()` builder and the v3 domain builders.\n *\n * The result is deep-cloned ({@link cloneMatchOpts}) so a caller mutating their\n * own `opts` object (or its nested `tokenizer`/`token_filters`) after this call\n * can never leak into the stored builder state or the emitted config — clone-on-\n * write for both builders, not just v3.\n */\nexport function resolveMatchOpts(opts?: MatchIndexOpts): BuiltMatchIndexOpts {\n const defaults = defaultMatchOpts()\n return cloneMatchOpts({\n tokenizer: opts?.tokenizer ?? defaults.tokenizer,\n token_filters: opts?.token_filters ?? defaults.token_filters,\n k: opts?.k ?? defaults.k,\n m: opts?.m ?? defaults.m,\n include_original: opts?.include_original ?? defaults.include_original,\n })\n}\n\n/**\n * The shortest needle a match index can answer, or `undefined` when its\n * tokenizer imposes no floor (`standard` splits on word boundaries, so any\n * non-empty needle yields at least one token).\n *\n * Accepts the loose {@link MatchIndexOpts} because a `ColumnSchema`'s built\n * `indexes.match` is typed from the zod schema, where `tokenizer` is optional.\n * An absent tokenizer resolves to the same default the schema itself applies\n * (`ngram`, `token_length: 3`) rather than skipping the floor — skipping would\n * reintroduce the fail-open this guard exists to close.\n */\nexport function matchNeedleMinLength(opts: MatchIndexOpts): number | undefined {\n const tokenizer = opts.tokenizer ?? defaultMatchOpts().tokenizer\n return tokenizer.kind === 'ngram' ? tokenizer.token_length : undefined\n}\n\n/**\n * Why a needle cannot be answered by this match index, or `undefined` when it\n * can. Callers throw their own error type with this as the reason.\n *\n * A needle that tokenizes to NOTHING has an empty bloom filter, and\n * `stored_bf @> '{}'` is true for every row (\"contains nothing, contained by\n * everything\"). Such a query is unanswerable rather than merely unmatched, so\n * it must fail loudly instead of silently returning the whole table. Two ways\n * to tokenize to nothing:\n *\n * - the empty needle, under ANY tokenizer;\n * - a needle shorter than the ngram tokenizer's `token_length`.\n *\n * The ngram floor counts Unicode CODEPOINTS, because that is what the tokenizer\n * counts. `needle.length` would count UTF-16 code units and wave through an\n * astral-plane needle: `'👍👍'` is 4 code units but only 2 codepoints, yields no\n * trigram, and (measured live) matched every row. Graphemes are the wrong unit\n * in the other direction — NFD `'éé'` is 4 codepoints but 2 grapheme clusters,\n * and does yield trigrams.\n *\n * Currently wired ONLY into the v3 Drizzle adapter (`eql/v3/drizzle/operators`).\n * It lives here, beside the shared match defaults, because v2 builds the same\n * bloom filters and needs the same floor — but v2's `like`/`ilike` path remains\n * unguarded and still fails open. Do not reuse this for v2 without first\n * measuring what its tokenizer actually receives: v2 needles carry SQL wildcards\n * (`'%ada%'`), so the floor may have to apply to the unwrapped term rather than\n * to the string the caller passed.\n */\nexport function matchNeedleError(\n needle: unknown,\n opts: MatchIndexOpts,\n): string | undefined {\n if (typeof needle !== 'string') return undefined\n\n // Codepoints, not UTF-16 code units — see above.\n const length = [...needle].length\n const min = matchNeedleMinLength(opts)\n\n if (length === 0) {\n return `free-text search needs a non-empty search term; an empty term produces no tokens and would match every row.`\n }\n if (min === undefined || length >= min) return undefined\n return `free-text search needs at least ${min} characters (the index tokenizer's token_length), but the search term ${JSON.stringify(needle)} has ${length}. A shorter term produces no tokens and would match every row.`\n}\n"],"mappings":";AAyCO,SAAS,mBAAwC;AACtD,SAAO;AAAA,IACL,WAAW,EAAE,MAAM,SAAS,cAAc,EAAE;AAAA,IAC5C,eAAe,CAAC,EAAE,MAAM,WAAW,CAAC;AAAA,IACpC,GAAG;AAAA,IACH,GAAG;AAAA,IACH,kBAAkB;AAAA,EACpB;AACF;AAOO,SAAS,eAAe,MAAgD;AAC7E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,EAAE,GAAG,KAAK,UAAU;AAAA,IAC/B,eAAe,KAAK,cAAc,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AAAA,EACzD;AACF;AAaO,SAAS,iBAAiB,MAA4C;AAC3E,QAAM,WAAW,iBAAiB;AAClC,SAAO,eAAe;AAAA,IACpB,WAAW,MAAM,aAAa,SAAS;AAAA,IACvC,eAAe,MAAM,iBAAiB,SAAS;AAAA,IAC/C,GAAG,MAAM,KAAK,SAAS;AAAA,IACvB,GAAG,MAAM,KAAK,SAAS;AAAA,IACvB,kBAAkB,MAAM,oBAAoB,SAAS;AAAA,EACvD,CAAC;AACH;AAaO,SAAS,qBAAqB,MAA0C;AAC7E,QAAM,YAAY,KAAK,aAAa,iBAAiB,EAAE;AACvD,SAAO,UAAU,SAAS,UAAU,UAAU,eAAe;AAC/D;AA8BO,SAAS,iBACd,QACA,MACoB;AACpB,MAAI,OAAO,WAAW,SAAU,QAAO;AAGvC,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE;AAC3B,QAAM,MAAM,qBAAqB,IAAI;AAErC,MAAI,WAAW,GAAG;AAChB,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,UAAa,UAAU,IAAK,QAAO;AAC/C,SAAO,mCAAmC,GAAG,yEAAyE,KAAK,UAAU,MAAM,CAAC,QAAQ,MAAM;AAC5J;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
- defaultMatchOpts
3
- } from "./chunk-IADZCZEA.js";
2
+ resolveMatchOpts
3
+ } from "./chunk-7333ZC6L.js";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-PZ5AY32C.js";
@@ -4102,6 +4102,7 @@ var tokenizerSchema = external_exports.union([
4102
4102
  })
4103
4103
  ]).default({ kind: "ngram", token_length: 3 }).optional();
4104
4104
  var oreIndexOptsSchema = external_exports.object({});
4105
+ var opeIndexOptsSchema = external_exports.object({});
4105
4106
  var uniqueIndexOptsSchema = external_exports.object({
4106
4107
  token_filters: external_exports.array(tokenFilterSchema).default([]).optional()
4107
4108
  });
@@ -4123,10 +4124,12 @@ var arrayIndexModeSchema = external_exports.union([
4123
4124
  ]);
4124
4125
  var steVecIndexOptsSchema = external_exports.object({
4125
4126
  prefix: external_exports.string(),
4126
- array_index_mode: arrayIndexModeSchema.optional()
4127
+ array_index_mode: arrayIndexModeSchema.optional(),
4128
+ mode: external_exports.enum(["compat", "standard"]).optional()
4127
4129
  });
4128
4130
  var indexesSchema = external_exports.object({
4129
4131
  ore: oreIndexOptsSchema.optional(),
4132
+ ope: opeIndexOptsSchema.optional(),
4130
4133
  unique: uniqueIndexOptsSchema.optional(),
4131
4134
  match: matchIndexOptsSchema.optional(),
4132
4135
  ste_vec: steVecIndexOptsSchema.optional()
@@ -4155,7 +4158,7 @@ var EncryptedField = class {
4155
4158
  * a different type so the encryption layer knows how to encode the plaintext
4156
4159
  * before encrypting.
4157
4160
  *
4158
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.
4161
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight.
4159
4162
  * @returns This `EncryptedField` instance for method chaining.
4160
4163
  *
4161
4164
  * @example
@@ -4194,7 +4197,7 @@ var EncryptedColumn = class {
4194
4197
  * a different type so the encryption layer knows how to encode the plaintext
4195
4198
  * before encrypting.
4196
4199
  *
4197
- * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
4200
+ * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight.
4198
4201
  * @returns This `EncryptedColumn` instance for method chaining.
4199
4202
  *
4200
4203
  * @example
@@ -4283,14 +4286,7 @@ var EncryptedColumn = class {
4283
4286
  * ```
4284
4287
  */
4285
4288
  freeTextSearch(opts) {
4286
- const defaults = defaultMatchOpts();
4287
- this.indexesValue.match = {
4288
- tokenizer: opts?.tokenizer ?? defaults.tokenizer,
4289
- token_filters: opts?.token_filters ?? defaults.token_filters,
4290
- k: opts?.k ?? defaults.k,
4291
- m: opts?.m ?? defaults.m,
4292
- include_original: opts?.include_original ?? defaults.include_original
4293
- };
4289
+ this.indexesValue.match = resolveMatchOpts(opts);
4294
4290
  return this;
4295
4291
  }
4296
4292
  /**
@@ -4317,7 +4313,11 @@ var EncryptedColumn = class {
4317
4313
  */
4318
4314
  searchableJson() {
4319
4315
  this.castAsValue = "json";
4320
- this.indexesValue.ste_vec = { prefix: "enabled", array_index_mode: "all" };
4316
+ this.indexesValue.ste_vec = {
4317
+ prefix: "enabled",
4318
+ array_index_mode: "all",
4319
+ mode: "standard"
4320
+ };
4321
4321
  return this;
4322
4322
  }
4323
4323
  build() {
@@ -4436,4 +4436,4 @@ export {
4436
4436
  encryptedField,
4437
4437
  buildEncryptConfig
4438
4438
  };
4439
- //# sourceMappingURL=chunk-MP3SSDNN.js.map
4439
+ //# sourceMappingURL=chunk-CLM7E4I6.js.map