@cipherstash/stack 0.10.0 → 0.11.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 (60) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/bin/stash.js +49 -103
  3. package/dist/bin/stash.js.map +1 -1
  4. package/dist/{chunk-HCL75LXQ.js → chunk-46PDK2Z6.js} +1 -1
  5. package/dist/chunk-46PDK2Z6.js.map +1 -0
  6. package/dist/{chunk-3BOJHROP.js → chunk-EHDOOLWU.js} +3 -3
  7. package/dist/{chunk-Y3KSTOVR.js → chunk-GNLU3I27.js} +14 -3
  8. package/dist/chunk-GNLU3I27.js.map +1 -0
  9. package/dist/{chunk-4C52Q5R6.js → chunk-O4MBO4DJ.js} +8 -22
  10. package/dist/chunk-O4MBO4DJ.js.map +1 -0
  11. package/dist/{client-_63nbmO7.d.ts → client-CZLBiToT.d.ts} +1 -7
  12. package/dist/{client-CV7X5Hrt.d.cts → client-bW-5wG9Y.d.cts} +1 -7
  13. package/dist/client.cjs +13 -2
  14. package/dist/client.cjs.map +1 -1
  15. package/dist/client.d.cts +2 -2
  16. package/dist/client.d.ts +2 -2
  17. package/dist/client.js +1 -1
  18. package/dist/drizzle/index.cjs +13 -2
  19. package/dist/drizzle/index.cjs.map +1 -1
  20. package/dist/drizzle/index.d.cts +2 -2
  21. package/dist/drizzle/index.d.ts +2 -2
  22. package/dist/drizzle/index.js +2 -2
  23. package/dist/dynamodb/index.d.cts +2 -2
  24. package/dist/dynamodb/index.d.ts +2 -2
  25. package/dist/encryption/index.cjs +22 -96
  26. package/dist/encryption/index.cjs.map +1 -1
  27. package/dist/encryption/index.d.cts +2 -2
  28. package/dist/encryption/index.d.ts +2 -2
  29. package/dist/encryption/index.js +3 -4
  30. package/dist/index.cjs +29 -81
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +3 -3
  33. package/dist/index.d.ts +3 -3
  34. package/dist/index.js +4 -4
  35. package/dist/schema/index.cjs +13 -2
  36. package/dist/schema/index.cjs.map +1 -1
  37. package/dist/schema/index.d.cts +1 -1
  38. package/dist/schema/index.d.ts +1 -1
  39. package/dist/schema/index.js +1 -1
  40. package/dist/secrets/index.cjs +29 -81
  41. package/dist/secrets/index.cjs.map +1 -1
  42. package/dist/secrets/index.d.cts +1 -1
  43. package/dist/secrets/index.d.ts +1 -1
  44. package/dist/secrets/index.js +4 -4
  45. package/dist/supabase/index.cjs +12 -2
  46. package/dist/supabase/index.cjs.map +1 -1
  47. package/dist/supabase/index.d.cts +2 -2
  48. package/dist/supabase/index.d.ts +2 -2
  49. package/dist/supabase/index.js +1 -1
  50. package/dist/{types-public-B5YxQhR6.d.cts → types-public-WADaA-TW.d.cts} +119 -1
  51. package/dist/{types-public-B5YxQhR6.d.ts → types-public-WADaA-TW.d.ts} +119 -1
  52. package/dist/types-public.cjs.map +1 -1
  53. package/dist/types-public.d.cts +1 -1
  54. package/dist/types-public.d.ts +1 -1
  55. package/dist/types-public.js +1 -1
  56. package/package.json +2 -2
  57. package/dist/chunk-4C52Q5R6.js.map +0 -1
  58. package/dist/chunk-HCL75LXQ.js.map +0 -1
  59. package/dist/chunk-Y3KSTOVR.js.map +0 -1
  60. /package/dist/{chunk-3BOJHROP.js.map → chunk-EHDOOLWU.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { E as Encrypted } from './types-public-B5YxQhR6.cjs';
2
- export { e as encryptedColumn, a as encryptedField, b as encryptedTable } from './types-public-B5YxQhR6.cjs';
3
- export { E as Encryption } from './client-CV7X5Hrt.cjs';
1
+ import { E as Encrypted } from './types-public-WADaA-TW.cjs';
2
+ export { e as encryptedColumn, a as encryptedField, b as encryptedTable } from './types-public-WADaA-TW.cjs';
3
+ export { E as Encryption } from './client-bW-5wG9Y.cjs';
4
4
  export { Secrets } from './secrets/index.cjs';
5
5
  import 'zod';
6
6
  import '@cipherstash/protect-ffi';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { E as Encrypted } from './types-public-B5YxQhR6.js';
2
- export { e as encryptedColumn, a as encryptedField, b as encryptedTable } from './types-public-B5YxQhR6.js';
3
- export { E as Encryption } from './client-_63nbmO7.js';
1
+ import { E as Encrypted } from './types-public-WADaA-TW.js';
2
+ export { e as encryptedColumn, a as encryptedField, b as encryptedTable } from './types-public-WADaA-TW.js';
3
+ export { E as Encryption } from './client-CZLBiToT.js';
4
4
  export { Secrets } from './secrets/index.js';
5
5
  import 'zod';
6
6
  import '@cipherstash/protect-ffi';
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Secrets
3
- } from "./chunk-3BOJHROP.js";
3
+ } from "./chunk-EHDOOLWU.js";
4
4
  import {
5
5
  Encryption
6
- } from "./chunk-4C52Q5R6.js";
6
+ } from "./chunk-O4MBO4DJ.js";
7
7
  import {
8
8
  encryptedToPgComposite,
9
9
  isEncryptedPayload
@@ -12,8 +12,8 @@ import {
12
12
  encryptedColumn,
13
13
  encryptedField,
14
14
  encryptedTable
15
- } from "./chunk-Y3KSTOVR.js";
16
- import "./chunk-HCL75LXQ.js";
15
+ } from "./chunk-GNLU3I27.js";
16
+ import "./chunk-46PDK2Z6.js";
17
17
  import "./chunk-GXGEW6T4.js";
18
18
  import "./chunk-Q5FTQLYG.js";
19
19
  import "./chunk-LBMC4D6D.js";
@@ -87,8 +87,18 @@ var matchIndexOptsSchema = import_zod.z.object({
87
87
  m: import_zod.z.number().default(2048).optional(),
88
88
  include_original: import_zod.z.boolean().default(false).optional()
89
89
  });
90
+ var arrayIndexModeSchema = import_zod.z.union([
91
+ import_zod.z.literal("all"),
92
+ import_zod.z.literal("none"),
93
+ import_zod.z.object({
94
+ item: import_zod.z.boolean().optional(),
95
+ wildcard: import_zod.z.boolean().optional(),
96
+ position: import_zod.z.boolean().optional()
97
+ })
98
+ ]);
90
99
  var steVecIndexOptsSchema = import_zod.z.object({
91
- prefix: import_zod.z.string()
100
+ prefix: import_zod.z.string(),
101
+ array_index_mode: arrayIndexModeSchema.optional()
92
102
  });
93
103
  var indexesSchema = import_zod.z.object({
94
104
  ore: oreIndexOptsSchema.optional(),
@@ -285,7 +295,7 @@ var EncryptedColumn = class {
285
295
  */
286
296
  searchableJson() {
287
297
  this.castAsValue = "json";
288
- this.indexesValue.ste_vec = { prefix: "enabled" };
298
+ this.indexesValue.ste_vec = { prefix: "enabled", array_index_mode: "all" };
289
299
  return this;
290
300
  }
291
301
  build() {
@@ -333,6 +343,7 @@ var EncryptedTable = class {
333
343
  indexes: {
334
344
  ...builtColumn.indexes,
335
345
  ste_vec: {
346
+ ...builtColumn.indexes.ste_vec,
336
347
  prefix: `${this.tableName}/${colName}`
337
348
  }
338
349
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/schema/index.ts"],"sourcesContent":["import type { Encrypted } from '@/types'\nimport { z } from 'zod'\n\n// ------------------------\n// Zod schemas\n// ------------------------\n\n/**\n * Allowed cast types for CipherStash schema fields.\n *\n * **Possible values:**\n * - `\"bigint\"`\n * - `\"boolean\"`\n * - `\"date\"`\n * - `\"number\"`\n * - `\"string\"`\n * - `\"json\"`\n * - `\"text\"`\n *\n * @remarks\n * This is a Zod enum used at runtime to validate schema definitions.\n * Use {@link CastAs} when typing your own code.\n *\n * @internal\n */\n/**\n * EQL cast types — the PostgreSQL-aligned types that EQL actually accepts.\n * These are stored in the `cast_as` field of the EncryptConfig.\n */\nexport const eqlCastAsEnum = z\n .enum([\n 'text',\n 'int',\n 'small_int',\n 'big_int',\n 'real',\n 'double',\n 'boolean',\n 'date',\n 'jsonb',\n ])\n .default('text')\n\n/**\n * SDK-facing data types — developer-friendly aliases accepted by `dataType()`.\n */\nexport const castAsEnum = z\n .enum(['bigint', 'boolean', 'date', 'number', 'string', 'json', 'text'])\n .default('text')\n\n/**\n * Map SDK-facing data types to EQL `cast_as` values.\n *\n * The SDK accepts developer-friendly types like `'string'` and `'number'`,\n * but EQL expects PostgreSQL-aligned types like `'text'` and `'double'`.\n */\nexport function toEqlCastAs(value: CastAs): EqlCastAs {\n switch (value) {\n case 'string':\n return 'text'\n case 'text':\n return 'text'\n case 'number':\n return 'double'\n case 'bigint':\n return 'big_int'\n case 'boolean':\n return 'boolean'\n case 'date':\n return 'date'\n case 'json':\n return 'jsonb'\n }\n}\n\nconst tokenFilterSchema = z.object({\n kind: z.literal('downcase'),\n})\n\nconst tokenizerSchema = z\n .union([\n z.object({\n kind: z.literal('standard'),\n }),\n z.object({\n kind: z.literal('ngram'),\n token_length: z.number(),\n }),\n ])\n .default({ kind: 'ngram', token_length: 3 })\n .optional()\n\nconst oreIndexOptsSchema = z.object({})\n\nconst uniqueIndexOptsSchema = z.object({\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n})\n\nconst matchIndexOptsSchema = z.object({\n tokenizer: tokenizerSchema,\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n k: z.number().default(6).optional(),\n m: z.number().default(2048).optional(),\n include_original: z.boolean().default(false).optional(),\n})\n\nconst steVecIndexOptsSchema = z.object({\n prefix: z.string(),\n})\n\nconst indexesSchema = z\n .object({\n ore: oreIndexOptsSchema.optional(),\n unique: uniqueIndexOptsSchema.optional(),\n match: matchIndexOptsSchema.optional(),\n ste_vec: steVecIndexOptsSchema.optional(),\n })\n .default({})\n\nconst columnSchema = z\n .object({\n cast_as: castAsEnum,\n indexes: indexesSchema,\n })\n .default({})\n\nconst tableSchema = z.record(columnSchema).default({})\n\nconst tablesSchema = z.record(tableSchema).default({})\n\n/** @internal */\nexport const encryptConfigSchema = z.object({\n v: z.number(),\n tables: tablesSchema,\n})\n\n// ------------------------\n// Type definitions\n// ------------------------\n\n/**\n * Type-safe alias for {@link castAsEnum} used to specify the *unencrypted* data type of a column or value.\n * This is important because once encrypted, all data is stored as binary blobs.\n *\n * @see {@link castAsEnum} for possible values.\n */\nexport type CastAs = z.infer<typeof castAsEnum>\nexport type EqlCastAs = z.infer<typeof eqlCastAsEnum>\nexport type TokenFilter = z.infer<typeof tokenFilterSchema>\nexport type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>\nexport type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>\nexport type UniqueIndexOpts = z.infer<typeof uniqueIndexOptsSchema>\nexport type OreIndexOpts = z.infer<typeof oreIndexOptsSchema>\nexport type ColumnSchema = z.infer<typeof columnSchema>\n\n/**\n * Shape of table columns: either top-level {@link EncryptedColumn} or nested\n * objects whose leaves are {@link EncryptedField}. Used with {@link encryptedTable}.\n */\nexport type EncryptedTableColumn = {\n [key: string]:\n | EncryptedColumn\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]: EncryptedField\n }\n }\n }\n}\nexport type EncryptConfig = z.infer<typeof encryptConfigSchema>\n\n// ------------------------\n// Interface definitions\n// ------------------------\n\n/**\n * Builder for a nested encrypted field (encrypted but not searchable).\n * Create with {@link encryptedField}. Use inside nested objects in {@link encryptedTable};\n * supports `.dataType()` for plaintext type. No index methods (equality, orderAndRange, etc.).\n */\nexport class EncryptedField {\n private valueName: string\n private castAsValue: CastAs\n\n constructor(valueName: string) {\n this.valueName = valueName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this field.\n *\n * By default all values are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedField` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const age = encryptedField(\"age\").dataType(\"number\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: {},\n }\n }\n\n getName() {\n return this.valueName\n }\n}\n\nexport class EncryptedColumn {\n private columnName: string\n private castAsValue: CastAs\n private indexesValue: {\n ore?: OreIndexOpts\n unique?: UniqueIndexOpts\n match?: Required<MatchIndexOpts>\n ste_vec?: SteVecIndexOpts\n } = {}\n\n constructor(columnName: string) {\n this.columnName = columnName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this column.\n *\n * By default all columns are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const dateOfBirth = encryptedColumn(\"date_of_birth\").dataType(\"date\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n /**\n * Enable Order-Revealing Encryption (ORE) indexing on this column.\n *\n * ORE allows sorting, comparison, and range queries on encrypted data.\n * Use with `encryptQuery` and `queryType: 'orderAndRange'`.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").orderAndRange(),\n * })\n * ```\n */\n orderAndRange() {\n this.indexesValue.ore = {}\n return this\n }\n\n /**\n * Enable an exact-match (unique) index on this column.\n *\n * Allows equality queries on encrypted data. Use with `encryptQuery`\n * and `queryType: 'equality'`.\n *\n * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).\n * When omitted, no token filters are applied.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n * ```\n */\n equality(tokenFilters?: TokenFilter[]) {\n this.indexesValue.unique = {\n token_filters: tokenFilters ?? [],\n }\n return this\n }\n\n /**\n * Enable a full-text / fuzzy search (match) index on this column.\n *\n * Uses n-gram tokenization by default for substring and fuzzy matching.\n * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.\n *\n * @param opts - Optional match index configuration. Defaults to 3-character ngram\n * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").freeTextSearch(),\n * })\n *\n * // With custom options\n * const posts = encryptedTable(\"posts\", {\n * body: encryptedColumn(\"body\").freeTextSearch({\n * tokenizer: { kind: \"ngram\", token_length: 4 },\n * k: 8,\n * m: 4096,\n * }),\n * })\n * ```\n */\n freeTextSearch(opts?: MatchIndexOpts) {\n // Provide defaults\n this.indexesValue.match = {\n tokenizer: opts?.tokenizer ?? { kind: 'ngram', token_length: 3 },\n token_filters: opts?.token_filters ?? [\n {\n kind: 'downcase',\n },\n ],\n k: opts?.k ?? 6,\n m: opts?.m ?? 2048,\n include_original: opts?.include_original ?? true,\n }\n return this\n }\n\n /**\n * Configure this column for searchable encrypted JSON (STE-Vec).\n *\n * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and\n * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the\n * data type to `'json'`.\n *\n * When used with `encryptQuery`, the query operation is auto-inferred from\n * the plaintext type: strings become selector queries, objects/arrays become\n * containment queries.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const documents = encryptedTable(\"documents\", {\n * metadata: encryptedColumn(\"metadata\").searchableJson(),\n * })\n * ```\n */\n searchableJson() {\n this.castAsValue = 'json'\n this.indexesValue.ste_vec = { prefix: 'enabled' }\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: this.indexesValue,\n }\n }\n\n getName() {\n return this.columnName\n }\n}\n\ninterface TableDefinition {\n tableName: string\n columns: Record<string, ColumnSchema>\n}\n\nexport class EncryptedTable<T extends EncryptedTableColumn> {\n /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */\n declare readonly _columnType: T\n\n constructor(\n public readonly tableName: string,\n private readonly columnBuilders: T,\n ) {}\n\n /**\n * Compile this table schema into a `TableDefinition` used internally by the encryption client.\n *\n * Iterates over all column builders, calls `.build()` on each, and assembles\n * the final `{ tableName, columns }` structure. For `searchableJson()` columns,\n * the STE-Vec prefix is automatically set to `\"<tableName>/<columnName>\"`.\n *\n * @returns A `TableDefinition` containing the table name and built column configs.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const definition = users.build()\n * // { tableName: \"users\", columns: { email: { cast_as: \"string\", indexes: { unique: ... } } } }\n * ```\n */\n build(): TableDefinition {\n const builtColumns: Record<string, ColumnSchema> = {}\n\n const processColumn = (\n builder:\n | EncryptedColumn\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n EncryptedField | Record<string, EncryptedField>\n >\n >\n >,\n colName: string,\n ) => {\n if (builder instanceof EncryptedColumn) {\n const builtColumn = builder.build()\n\n // Hanlde building the ste_vec index for JSON columns so users don't have to pass the prefix.\n if (\n builtColumn.cast_as === 'json' &&\n builtColumn.indexes.ste_vec?.prefix === 'enabled'\n ) {\n builtColumns[colName] = {\n ...builtColumn,\n indexes: {\n ...builtColumn.indexes,\n ste_vec: {\n prefix: `${this.tableName}/${colName}`,\n },\n },\n }\n } else {\n builtColumns[colName] = builtColumn\n }\n } else {\n for (const [key, value] of Object.entries(builder)) {\n if (value instanceof EncryptedField) {\n builtColumns[value.getName()] = value.build()\n } else {\n processColumn(value, key)\n }\n }\n }\n }\n\n for (const [colName, builder] of Object.entries(this.columnBuilders)) {\n processColumn(builder, colName)\n }\n\n return {\n tableName: this.tableName,\n columns: builtColumns,\n }\n }\n}\n\n// ------------------------\n// Schema type inference helpers\n// ------------------------\n\n/**\n * Infer the plaintext (decrypted) type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * name: encryptedColumn(\"name\"),\n * })\n *\n * type UserPlaintext = InferPlaintext<typeof users>\n * // => { email: string; name: string }\n * ```\n */\nexport type InferPlaintext<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: string\n }\n : never\n\n/**\n * Infer the encrypted type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * type UserEncrypted = InferEncrypted<typeof users>\n * // => { email: Encrypted }\n * ```\n */\nexport type InferEncrypted<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: Encrypted\n }\n : never\n\n// ------------------------\n// User facing functions\n// ------------------------\n\n/**\n * Define an encrypted table schema.\n *\n * Creates a `EncryptedTable` that maps a database table name to a set of encrypted\n * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`\n * when initializing the client.\n *\n * The returned object is also a proxy that exposes each column builder directly,\n * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,\n * and `encryptQuery`.\n *\n * @param tableName - The name of the database table this schema represents.\n * @param columns - An object whose keys are logical column names and values are\n * {@link EncryptedColumn} from {@link encryptedColumn}, or nested objects whose\n * leaves are {@link EncryptedField} from {@link encryptedField}.\n * @returns A `EncryptedTable<T> & T` that can be used as both a schema definition\n * and a column accessor.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch(),\n * address: encryptedColumn(\"address\"),\n * })\n *\n * // Use as schema\n * const client = await Encryption({ schemas: [users] })\n *\n * // Use as column accessor\n * await client.encrypt(\"hello@example.com\", { column: users.email, table: users })\n * ```\n */\nexport function encryptedTable<T extends EncryptedTableColumn>(\n tableName: string,\n columns: T,\n): EncryptedTable<T> & T {\n const tableBuilder = new EncryptedTable(\n tableName,\n columns,\n ) as EncryptedTable<T> & T\n\n for (const [colName, colBuilder] of Object.entries(columns)) {\n ;(tableBuilder as EncryptedTableColumn)[colName] = colBuilder\n }\n\n return tableBuilder\n}\n\n/**\n * Define an encrypted column within a table schema.\n *\n * Creates a `EncryptedColumn` builder for the given column name. Chain index\n * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,\n * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption\n * and the plaintext data type.\n *\n * @param columnName - The name of the database column to encrypt.\n * @returns A new `EncryptedColumn` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch().orderAndRange(),\n * })\n * ```\n */\nexport function encryptedColumn(columnName: string) {\n return new EncryptedColumn(columnName)\n}\n\n/**\n * Define an encrypted field for use in nested or structured schemas.\n *\n * `encryptedField` is similar to {@link encryptedColumn} but creates an {@link EncryptedField}\n * for nested fields that are encrypted but not searchable (no indexes). Use `.dataType()`\n * to specify the plaintext type.\n *\n * @param valueName - The name of the value field.\n * @returns A new `EncryptedField` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const orders = encryptedTable(\"orders\", {\n * details: {\n * amount: encryptedField(\"amount\").dataType(\"number\"),\n * currency: encryptedField(\"currency\"),\n * },\n * })\n * ```\n */\nexport function encryptedField(valueName: string) {\n return new EncryptedField(valueName)\n}\n\n/**\n * Build an encrypt config from a list of encrypted tables.\n *\n * @param ...tables - The list of encrypted tables to build the config from.\n * @returns An encrypt config object.\n *\n * @example\n * ```typescript\n * import { buildEncryptConfig } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const orders = encryptedTable(\"orders\", {\n * amount: encryptedColumn(\"amount\").dataType(\"number\"),\n * })\n *\n * const config = buildEncryptConfig(users, orders)\n * console.log(config)\n * ```\n */\nexport function buildEncryptConfig(\n ...protectTables: Array<EncryptedTable<EncryptedTableColumn>>\n): EncryptConfig {\n const config: EncryptConfig = {\n v: 2,\n tables: {},\n }\n\n for (const tb of protectTables) {\n const tableDef = tb.build()\n config.tables[tableDef.tableName] = tableDef.columns\n }\n\n return config\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/schema/index.ts"],"sourcesContent":["import type { Encrypted } from '@/types'\nimport { z } from 'zod'\n\n// ------------------------\n// Zod schemas\n// ------------------------\n\n/**\n * Allowed cast types for CipherStash schema fields.\n *\n * **Possible values:**\n * - `\"bigint\"`\n * - `\"boolean\"`\n * - `\"date\"`\n * - `\"number\"`\n * - `\"string\"`\n * - `\"json\"`\n * - `\"text\"`\n *\n * @remarks\n * This is a Zod enum used at runtime to validate schema definitions.\n * Use {@link CastAs} when typing your own code.\n *\n * @internal\n */\n/**\n * EQL cast types — the PostgreSQL-aligned types that EQL actually accepts.\n * These are stored in the `cast_as` field of the EncryptConfig.\n */\nexport const eqlCastAsEnum = z\n .enum([\n 'text',\n 'int',\n 'small_int',\n 'big_int',\n 'real',\n 'double',\n 'boolean',\n 'date',\n 'jsonb',\n ])\n .default('text')\n\n/**\n * SDK-facing data types — developer-friendly aliases accepted by `dataType()`.\n */\nexport const castAsEnum = z\n .enum(['bigint', 'boolean', 'date', 'number', 'string', 'json', 'text'])\n .default('text')\n\n/**\n * Map SDK-facing data types to EQL `cast_as` values.\n *\n * The SDK accepts developer-friendly types like `'string'` and `'number'`,\n * but EQL expects PostgreSQL-aligned types like `'text'` and `'double'`.\n */\nexport function toEqlCastAs(value: CastAs): EqlCastAs {\n switch (value) {\n case 'string':\n return 'text'\n case 'text':\n return 'text'\n case 'number':\n return 'double'\n case 'bigint':\n return 'big_int'\n case 'boolean':\n return 'boolean'\n case 'date':\n return 'date'\n case 'json':\n return 'jsonb'\n }\n}\n\nconst tokenFilterSchema = z.object({\n kind: z.literal('downcase'),\n})\n\nconst tokenizerSchema = z\n .union([\n z.object({\n kind: z.literal('standard'),\n }),\n z.object({\n kind: z.literal('ngram'),\n token_length: z.number(),\n }),\n ])\n .default({ kind: 'ngram', token_length: 3 })\n .optional()\n\nconst oreIndexOptsSchema = z.object({})\n\nconst uniqueIndexOptsSchema = z.object({\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n})\n\nconst matchIndexOptsSchema = z.object({\n tokenizer: tokenizerSchema,\n token_filters: z.array(tokenFilterSchema).default([]).optional(),\n k: z.number().default(6).optional(),\n m: z.number().default(2048).optional(),\n include_original: z.boolean().default(false).optional(),\n})\n\nconst arrayIndexModeSchema = z.union([\n z.literal('all'),\n z.literal('none'),\n z.object({\n item: z.boolean().optional(),\n wildcard: z.boolean().optional(),\n position: z.boolean().optional(),\n }),\n])\n\nconst steVecIndexOptsSchema = z.object({\n prefix: z.string(),\n array_index_mode: arrayIndexModeSchema.optional(),\n})\n\nconst indexesSchema = z\n .object({\n ore: oreIndexOptsSchema.optional(),\n unique: uniqueIndexOptsSchema.optional(),\n match: matchIndexOptsSchema.optional(),\n ste_vec: steVecIndexOptsSchema.optional(),\n })\n .default({})\n\nconst columnSchema = z\n .object({\n cast_as: castAsEnum,\n indexes: indexesSchema,\n })\n .default({})\n\nconst tableSchema = z.record(columnSchema).default({})\n\nconst tablesSchema = z.record(tableSchema).default({})\n\n/** @internal */\nexport const encryptConfigSchema = z.object({\n v: z.number(),\n tables: tablesSchema,\n})\n\n// ------------------------\n// Type definitions\n// ------------------------\n\n/**\n * Type-safe alias for {@link castAsEnum} used to specify the *unencrypted* data type of a column or value.\n * This is important because once encrypted, all data is stored as binary blobs.\n *\n * @see {@link castAsEnum} for possible values.\n */\nexport type CastAs = z.infer<typeof castAsEnum>\nexport type EqlCastAs = z.infer<typeof eqlCastAsEnum>\nexport type TokenFilter = z.infer<typeof tokenFilterSchema>\nexport type MatchIndexOpts = z.infer<typeof matchIndexOptsSchema>\nexport type SteVecIndexOpts = z.infer<typeof steVecIndexOptsSchema>\nexport type UniqueIndexOpts = z.infer<typeof uniqueIndexOptsSchema>\nexport type OreIndexOpts = z.infer<typeof oreIndexOptsSchema>\nexport type ColumnSchema = z.infer<typeof columnSchema>\n\n/**\n * Shape of table columns: either top-level {@link EncryptedColumn} or nested\n * objects whose leaves are {@link EncryptedField}. Used with {@link encryptedTable}.\n */\nexport type EncryptedTableColumn = {\n [key: string]:\n | EncryptedColumn\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]:\n | EncryptedField\n | {\n [key: string]: EncryptedField\n }\n }\n }\n}\nexport type EncryptConfig = z.infer<typeof encryptConfigSchema>\n\n// ------------------------\n// Interface definitions\n// ------------------------\n\n/**\n * Builder for a nested encrypted field (encrypted but not searchable).\n * Create with {@link encryptedField}. Use inside nested objects in {@link encryptedTable};\n * supports `.dataType()` for plaintext type. No index methods (equality, orderAndRange, etc.).\n */\nexport class EncryptedField {\n private valueName: string\n private castAsValue: CastAs\n\n constructor(valueName: string) {\n this.valueName = valueName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this field.\n *\n * By default all values are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedField` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const age = encryptedField(\"age\").dataType(\"number\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: {},\n }\n }\n\n getName() {\n return this.valueName\n }\n}\n\nexport class EncryptedColumn {\n private columnName: string\n private castAsValue: CastAs\n private indexesValue: {\n ore?: OreIndexOpts\n unique?: UniqueIndexOpts\n match?: Required<MatchIndexOpts>\n ste_vec?: SteVecIndexOpts\n } = {}\n\n constructor(columnName: string) {\n this.columnName = columnName\n this.castAsValue = 'string'\n }\n\n /**\n * Set or override the plaintext data type for this column.\n *\n * By default all columns are treated as `'string'`. Use this method to specify\n * a different type so the encryption layer knows how to encode the plaintext\n * before encrypting.\n *\n * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const dateOfBirth = encryptedColumn(\"date_of_birth\").dataType(\"date\")\n * ```\n */\n dataType(castAs: CastAs) {\n this.castAsValue = castAs\n return this\n }\n\n /**\n * Enable Order-Revealing Encryption (ORE) indexing on this column.\n *\n * ORE allows sorting, comparison, and range queries on encrypted data.\n * Use with `encryptQuery` and `queryType: 'orderAndRange'`.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").orderAndRange(),\n * })\n * ```\n */\n orderAndRange() {\n this.indexesValue.ore = {}\n return this\n }\n\n /**\n * Enable an exact-match (unique) index on this column.\n *\n * Allows equality queries on encrypted data. Use with `encryptQuery`\n * and `queryType: 'equality'`.\n *\n * @param tokenFilters - Optional array of token filters (e.g. `[{ kind: 'downcase' }]`).\n * When omitted, no token filters are applied.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n * ```\n */\n equality(tokenFilters?: TokenFilter[]) {\n this.indexesValue.unique = {\n token_filters: tokenFilters ?? [],\n }\n return this\n }\n\n /**\n * Enable a full-text / fuzzy search (match) index on this column.\n *\n * Uses n-gram tokenization by default for substring and fuzzy matching.\n * Use with `encryptQuery` and `queryType: 'freeTextSearch'`.\n *\n * @param opts - Optional match index configuration. Defaults to 3-character ngram\n * tokenization with a downcase filter, `k=6`, `m=2048`, and `include_original=true`.\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").freeTextSearch(),\n * })\n *\n * // With custom options\n * const posts = encryptedTable(\"posts\", {\n * body: encryptedColumn(\"body\").freeTextSearch({\n * tokenizer: { kind: \"ngram\", token_length: 4 },\n * k: 8,\n * m: 4096,\n * }),\n * })\n * ```\n */\n freeTextSearch(opts?: MatchIndexOpts) {\n // Provide defaults\n this.indexesValue.match = {\n tokenizer: opts?.tokenizer ?? { kind: 'ngram', token_length: 3 },\n token_filters: opts?.token_filters ?? [\n {\n kind: 'downcase',\n },\n ],\n k: opts?.k ?? 6,\n m: opts?.m ?? 2048,\n include_original: opts?.include_original ?? true,\n }\n return this\n }\n\n /**\n * Configure this column for searchable encrypted JSON (STE-Vec).\n *\n * Enables encrypted JSONPath selector queries (e.g. `'$.user.email'`) and\n * containment queries (e.g. `{ role: 'admin' }`). Automatically sets the\n * data type to `'json'`.\n *\n * When used with `encryptQuery`, the query operation is auto-inferred from\n * the plaintext type: strings become selector queries, objects/arrays become\n * containment queries.\n *\n * @returns This `EncryptedColumn` instance for method chaining.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const documents = encryptedTable(\"documents\", {\n * metadata: encryptedColumn(\"metadata\").searchableJson(),\n * })\n * ```\n */\n searchableJson() {\n this.castAsValue = 'json'\n this.indexesValue.ste_vec = { prefix: 'enabled', array_index_mode: 'all' }\n return this\n }\n\n build() {\n return {\n cast_as: this.castAsValue,\n indexes: this.indexesValue,\n }\n }\n\n getName() {\n return this.columnName\n }\n}\n\ninterface TableDefinition {\n tableName: string\n columns: Record<string, ColumnSchema>\n}\n\nexport class EncryptedTable<T extends EncryptedTableColumn> {\n /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */\n declare readonly _columnType: T\n\n constructor(\n public readonly tableName: string,\n private readonly columnBuilders: T,\n ) {}\n\n /**\n * Compile this table schema into a `TableDefinition` used internally by the encryption client.\n *\n * Iterates over all column builders, calls `.build()` on each, and assembles\n * the final `{ tableName, columns }` structure. For `searchableJson()` columns,\n * the STE-Vec prefix is automatically set to `\"<tableName>/<columnName>\"`.\n *\n * @returns A `TableDefinition` containing the table name and built column configs.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const definition = users.build()\n * // { tableName: \"users\", columns: { email: { cast_as: \"string\", indexes: { unique: ... } } } }\n * ```\n */\n build(): TableDefinition {\n const builtColumns: Record<string, ColumnSchema> = {}\n\n const processColumn = (\n builder:\n | EncryptedColumn\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n | EncryptedField\n | Record<\n string,\n EncryptedField | Record<string, EncryptedField>\n >\n >\n >,\n colName: string,\n ) => {\n if (builder instanceof EncryptedColumn) {\n const builtColumn = builder.build()\n\n // Hanlde building the ste_vec index for JSON columns so users don't have to pass the prefix.\n if (\n builtColumn.cast_as === 'json' &&\n builtColumn.indexes.ste_vec?.prefix === 'enabled'\n ) {\n builtColumns[colName] = {\n ...builtColumn,\n indexes: {\n ...builtColumn.indexes,\n ste_vec: {\n ...builtColumn.indexes.ste_vec,\n prefix: `${this.tableName}/${colName}`,\n },\n },\n }\n } else {\n builtColumns[colName] = builtColumn\n }\n } else {\n for (const [key, value] of Object.entries(builder)) {\n if (value instanceof EncryptedField) {\n builtColumns[value.getName()] = value.build()\n } else {\n processColumn(value, key)\n }\n }\n }\n }\n\n for (const [colName, builder] of Object.entries(this.columnBuilders)) {\n processColumn(builder, colName)\n }\n\n return {\n tableName: this.tableName,\n columns: builtColumns,\n }\n }\n}\n\n// ------------------------\n// Schema type inference helpers\n// ------------------------\n\n/**\n * Infer the plaintext (decrypted) type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * name: encryptedColumn(\"name\"),\n * })\n *\n * type UserPlaintext = InferPlaintext<typeof users>\n * // => { email: string; name: string }\n * ```\n */\nexport type InferPlaintext<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: string\n }\n : never\n\n/**\n * Infer the encrypted type from a EncryptedTable schema.\n *\n * @example\n * ```typescript\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * type UserEncrypted = InferEncrypted<typeof users>\n * // => { email: Encrypted }\n * ```\n */\nexport type InferEncrypted<T extends EncryptedTable<any>> =\n T extends EncryptedTable<infer C>\n ? {\n [K in keyof C as C[K] extends EncryptedColumn | EncryptedField\n ? K\n : never]: Encrypted\n }\n : never\n\n// ------------------------\n// User facing functions\n// ------------------------\n\n/**\n * Define an encrypted table schema.\n *\n * Creates a `EncryptedTable` that maps a database table name to a set of encrypted\n * column definitions. Pass the resulting object to `Encryption({ schemas: [...] })`\n * when initializing the client.\n *\n * The returned object is also a proxy that exposes each column builder directly,\n * so you can reference columns as `users.email` when calling `encrypt`, `decrypt`,\n * and `encryptQuery`.\n *\n * @param tableName - The name of the database table this schema represents.\n * @param columns - An object whose keys are logical column names and values are\n * {@link EncryptedColumn} from {@link encryptedColumn}, or nested objects whose\n * leaves are {@link EncryptedField} from {@link encryptedField}.\n * @returns A `EncryptedTable<T> & T` that can be used as both a schema definition\n * and a column accessor.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch(),\n * address: encryptedColumn(\"address\"),\n * })\n *\n * // Use as schema\n * const client = await Encryption({ schemas: [users] })\n *\n * // Use as column accessor\n * await client.encrypt(\"hello@example.com\", { column: users.email, table: users })\n * ```\n */\nexport function encryptedTable<T extends EncryptedTableColumn>(\n tableName: string,\n columns: T,\n): EncryptedTable<T> & T {\n const tableBuilder = new EncryptedTable(\n tableName,\n columns,\n ) as EncryptedTable<T> & T\n\n for (const [colName, colBuilder] of Object.entries(columns)) {\n ;(tableBuilder as EncryptedTableColumn)[colName] = colBuilder\n }\n\n return tableBuilder\n}\n\n/**\n * Define an encrypted column within a table schema.\n *\n * Creates a `EncryptedColumn` builder for the given column name. Chain index\n * methods (`.equality()`, `.freeTextSearch()`, `.orderAndRange()`,\n * `.searchableJson()`) and/or `.dataType()` to configure searchable encryption\n * and the plaintext data type.\n *\n * @param columnName - The name of the database column to encrypt.\n * @returns A new `EncryptedColumn` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality().freeTextSearch().orderAndRange(),\n * })\n * ```\n */\nexport function encryptedColumn(columnName: string) {\n return new EncryptedColumn(columnName)\n}\n\n/**\n * Define an encrypted field for use in nested or structured schemas.\n *\n * `encryptedField` is similar to {@link encryptedColumn} but creates an {@link EncryptedField}\n * for nested fields that are encrypted but not searchable (no indexes). Use `.dataType()`\n * to specify the plaintext type.\n *\n * @param valueName - The name of the value field.\n * @returns A new `EncryptedField` builder.\n *\n * @example\n * ```typescript\n * import { encryptedTable, encryptedField } from \"@cipherstash/stack/schema\"\n *\n * const orders = encryptedTable(\"orders\", {\n * details: {\n * amount: encryptedField(\"amount\").dataType(\"number\"),\n * currency: encryptedField(\"currency\"),\n * },\n * })\n * ```\n */\nexport function encryptedField(valueName: string) {\n return new EncryptedField(valueName)\n}\n\n/**\n * Build an encrypt config from a list of encrypted tables.\n *\n * @param ...tables - The list of encrypted tables to build the config from.\n * @returns An encrypt config object.\n *\n * @example\n * ```typescript\n * import { buildEncryptConfig } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const orders = encryptedTable(\"orders\", {\n * amount: encryptedColumn(\"amount\").dataType(\"number\"),\n * })\n *\n * const config = buildEncryptConfig(users, orders)\n * console.log(config)\n * ```\n */\nexport function buildEncryptConfig(\n ...protectTables: Array<EncryptedTable<EncryptedTableColumn>>\n): EncryptConfig {\n const config: EncryptConfig = {\n v: 2,\n tables: {},\n }\n\n for (const tb of protectTables) {\n const tableDef = tb.build()\n config.tables[tableDef.tableName] = tableDef.columns\n }\n\n return config\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,3 @@
1
- export { C as CastAs, u as ColumnSchema, q as EncryptConfig, f as EncryptedColumn, n as EncryptedField, c as EncryptedTable, d as EncryptedTableColumn, v as EqlCastAs, I as InferEncrypted, t as InferPlaintext, M as MatchIndexOpts, O as OreIndexOpts, w as SteVecIndexOpts, T as TokenFilter, U as UniqueIndexOpts, x as buildEncryptConfig, y as castAsEnum, z as encryptConfigSchema, e as encryptedColumn, a as encryptedField, b as encryptedTable, A as eqlCastAsEnum, F as toEqlCastAs } from '../types-public-B5YxQhR6.cjs';
1
+ export { C as CastAs, u as ColumnSchema, q as EncryptConfig, f as EncryptedColumn, n as EncryptedField, c as EncryptedTable, d as EncryptedTableColumn, v as EqlCastAs, I as InferEncrypted, t as InferPlaintext, M as MatchIndexOpts, O as OreIndexOpts, w as SteVecIndexOpts, T as TokenFilter, U as UniqueIndexOpts, x as buildEncryptConfig, y as castAsEnum, z as encryptConfigSchema, e as encryptedColumn, a as encryptedField, b as encryptedTable, A as eqlCastAsEnum, F as toEqlCastAs } from '../types-public-WADaA-TW.cjs';
2
2
  import 'zod';
3
3
  import '@cipherstash/protect-ffi';
@@ -1,3 +1,3 @@
1
- export { C as CastAs, u as ColumnSchema, q as EncryptConfig, f as EncryptedColumn, n as EncryptedField, c as EncryptedTable, d as EncryptedTableColumn, v as EqlCastAs, I as InferEncrypted, t as InferPlaintext, M as MatchIndexOpts, O as OreIndexOpts, w as SteVecIndexOpts, T as TokenFilter, U as UniqueIndexOpts, x as buildEncryptConfig, y as castAsEnum, z as encryptConfigSchema, e as encryptedColumn, a as encryptedField, b as encryptedTable, A as eqlCastAsEnum, F as toEqlCastAs } from '../types-public-B5YxQhR6.js';
1
+ export { C as CastAs, u as ColumnSchema, q as EncryptConfig, f as EncryptedColumn, n as EncryptedField, c as EncryptedTable, d as EncryptedTableColumn, v as EqlCastAs, I as InferEncrypted, t as InferPlaintext, M as MatchIndexOpts, O as OreIndexOpts, w as SteVecIndexOpts, T as TokenFilter, U as UniqueIndexOpts, x as buildEncryptConfig, y as castAsEnum, z as encryptConfigSchema, e as encryptedColumn, a as encryptedField, b as encryptedTable, A as eqlCastAsEnum, F as toEqlCastAs } from '../types-public-WADaA-TW.js';
2
2
  import 'zod';
3
3
  import '@cipherstash/protect-ffi';
@@ -10,7 +10,7 @@ import {
10
10
  encryptedTable,
11
11
  eqlCastAsEnum,
12
12
  toEqlCastAs
13
- } from "../chunk-Y3KSTOVR.js";
13
+ } from "../chunk-GNLU3I27.js";
14
14
  export {
15
15
  EncryptedColumn,
16
16
  EncryptedField,
@@ -109,8 +109,18 @@ var matchIndexOptsSchema = import_zod.z.object({
109
109
  m: import_zod.z.number().default(2048).optional(),
110
110
  include_original: import_zod.z.boolean().default(false).optional()
111
111
  });
112
+ var arrayIndexModeSchema = import_zod.z.union([
113
+ import_zod.z.literal("all"),
114
+ import_zod.z.literal("none"),
115
+ import_zod.z.object({
116
+ item: import_zod.z.boolean().optional(),
117
+ wildcard: import_zod.z.boolean().optional(),
118
+ position: import_zod.z.boolean().optional()
119
+ })
120
+ ]);
112
121
  var steVecIndexOptsSchema = import_zod.z.object({
113
- prefix: import_zod.z.string()
122
+ prefix: import_zod.z.string(),
123
+ array_index_mode: arrayIndexModeSchema.optional()
114
124
  });
115
125
  var indexesSchema = import_zod.z.object({
116
126
  ore: oreIndexOptsSchema.optional(),
@@ -307,7 +317,7 @@ var EncryptedColumn = class {
307
317
  */
308
318
  searchableJson() {
309
319
  this.castAsValue = "json";
310
- this.indexesValue.ste_vec = { prefix: "enabled" };
320
+ this.indexesValue.ste_vec = { prefix: "enabled", array_index_mode: "all" };
311
321
  return this;
312
322
  }
313
323
  build() {
@@ -355,6 +365,7 @@ var EncryptedTable = class {
355
365
  indexes: {
356
366
  ...builtColumn.indexes,
357
367
  ste_vec: {
368
+ ...builtColumn.indexes.ste_vec,
358
369
  prefix: `${this.tableName}/${colName}`
359
370
  }
360
371
  }
@@ -416,69 +427,6 @@ var EncryptionErrorTypes = {
416
427
  CtsTokenError: "CtsTokenError"
417
428
  };
418
429
 
419
- // src/utils/config/index.ts
420
- var import_node_fs = __toESM(require("fs"), 1);
421
- var import_node_path = __toESM(require("path"), 1);
422
- function getWorkspaceCrn(tomlString) {
423
- let currentSection = "";
424
- let workspaceCrn;
425
- const lines = tomlString.split(/\r?\n/);
426
- for (const line of lines) {
427
- const trimmedLine = line.trim();
428
- if (!trimmedLine || trimmedLine.startsWith("#")) {
429
- continue;
430
- }
431
- const sectionMatch = trimmedLine.match(/^\[([^\]]+)\]$/);
432
- if (sectionMatch) {
433
- currentSection = sectionMatch[1];
434
- continue;
435
- }
436
- const kvMatch = trimmedLine.match(/^(\w+)\s*=\s*"([^"]+)"$/);
437
- if (kvMatch) {
438
- const [_, key, value] = kvMatch;
439
- if (currentSection === "auth" && key === "workspace_crn") {
440
- workspaceCrn = value;
441
- break;
442
- }
443
- }
444
- }
445
- return workspaceCrn;
446
- }
447
- function extractWorkspaceIdFromCrn(crn) {
448
- const match = crn.match(/crn:[^:]+:([^:]+)$/);
449
- if (!match) {
450
- throw new Error("Invalid CRN format");
451
- }
452
- return match[1];
453
- }
454
- function loadWorkSpaceId(suppliedCrn) {
455
- const configPath = import_node_path.default.join(process.cwd(), "cipherstash.toml");
456
- if (suppliedCrn) {
457
- return extractWorkspaceIdFromCrn(suppliedCrn);
458
- }
459
- if (!import_node_fs.default.existsSync(configPath) && !process.env.CS_WORKSPACE_CRN) {
460
- throw new Error(
461
- "You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable."
462
- );
463
- }
464
- if (process.env.CS_WORKSPACE_CRN) {
465
- return extractWorkspaceIdFromCrn(process.env.CS_WORKSPACE_CRN);
466
- }
467
- if (!import_node_fs.default.existsSync(configPath)) {
468
- throw new Error(
469
- "You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable."
470
- );
471
- }
472
- const tomlString = import_node_fs.default.readFileSync(configPath, "utf8");
473
- const workspaceCrn = getWorkspaceCrn(tomlString);
474
- if (!workspaceCrn) {
475
- throw new Error(
476
- "You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable."
477
- );
478
- }
479
- return extractWorkspaceIdFromCrn(workspaceCrn);
480
- }
481
-
482
430
  // src/utils/logger/index.ts
483
431
  var import_evlog = require("evlog");
484
432
  var validLevels = ["debug", "info", "error"];
@@ -2400,11 +2348,6 @@ var noClientError = () => new Error(
2400
2348
  var EncryptionClient = class {
2401
2349
  client;
2402
2350
  encryptConfig;
2403
- workspaceId;
2404
- constructor(workspaceCrn) {
2405
- const workspaceId = loadWorkSpaceId(workspaceCrn);
2406
- this.workspaceId = workspaceId;
2407
- }
2408
2351
  /**
2409
2352
  * Initializes the EncryptionClient with the provided configuration.
2410
2353
  * @internal
@@ -2426,10 +2369,10 @@ var EncryptionClient = class {
2426
2369
  this.client = await (0, import_protect_ffi9.newClient)({
2427
2370
  encryptConfig: validated,
2428
2371
  clientOpts: {
2429
- workspaceCrn: config.workspaceCrn ?? process.env.CS_WORKSPACE_CRN,
2430
- accessKey: config.accessKey ?? process.env.CS_CLIENT_ACCESS_KEY,
2431
- clientId: config.clientId ?? process.env.CS_CLIENT_ID,
2432
- clientKey: config.clientKey ?? process.env.CS_CLIENT_KEY,
2372
+ workspaceCrn: config.workspaceCrn,
2373
+ accessKey: config.accessKey,
2374
+ clientId: config.clientId,
2375
+ clientKey: config.clientKey,
2433
2376
  keyset: toFfiKeysetIdentifier(config.keyset)
2434
2377
  }
2435
2378
  });
@@ -2814,12 +2757,6 @@ var EncryptionClient = class {
2814
2757
  bulkDecrypt(encryptedPayloads) {
2815
2758
  return new BulkDecryptOperation(this.client, encryptedPayloads);
2816
2759
  }
2817
- /** e.g., debugging or environment info */
2818
- clientInfo() {
2819
- return {
2820
- workspaceId: this.workspaceId
2821
- };
2822
- }
2823
2760
  /**
2824
2761
  * Get the encrypt config object.
2825
2762
  *
@@ -2841,7 +2778,7 @@ var Encryption = async (config) => {
2841
2778
  "[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
2842
2779
  );
2843
2780
  }
2844
- const client = new EncryptionClient(clientConfig?.workspaceCrn);
2781
+ const client = new EncryptionClient();
2845
2782
  const encryptConfig = buildEncryptConfig(...schemas);
2846
2783
  const result = await client.init({
2847
2784
  encryptConfig,
@@ -2853,6 +2790,17 @@ var Encryption = async (config) => {
2853
2790
  return result.data;
2854
2791
  };
2855
2792
 
2793
+ // src/utils/config/index.ts
2794
+ var import_node_fs = __toESM(require("fs"), 1);
2795
+ var import_node_path = __toESM(require("path"), 1);
2796
+ function extractWorkspaceIdFromCrn(crn) {
2797
+ const match = crn.match(/crn:[^:]+:([^:]+)$/);
2798
+ if (!match) {
2799
+ throw new Error("Invalid CRN format");
2800
+ }
2801
+ return match[1];
2802
+ }
2803
+
2856
2804
  // src/secrets/index.ts
2857
2805
  var Secrets = class {
2858
2806
  encryptionClient = null;