@cipherstash/stack 0.3.0 → 0.4.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.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/bin/stash.js +46 -141
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-SUYMGQBY.js → chunk-4RNBI3UH.js} +1 -7
- package/dist/chunk-4RNBI3UH.js.map +1 -0
- package/dist/{chunk-JLI27P46.js → chunk-KOU2MHXJ.js} +1 -1
- package/dist/chunk-KOU2MHXJ.js.map +1 -0
- package/dist/{chunk-MW6D52V2.js → chunk-WUZGKTMG.js} +45 -134
- package/dist/chunk-WUZGKTMG.js.map +1 -0
- package/dist/{chunk-TBAIVO6T.js → chunk-Y35W4WFN.js} +6 -6
- package/dist/chunk-Y35W4WFN.js.map +1 -0
- package/dist/{client-Bf0Xw2xo.d.cts → client-CUGXheRq.d.cts} +15 -16
- package/dist/{client-Kfp8OsPB.d.ts → client-CrGQnSlk.d.ts} +15 -16
- package/dist/client.cjs +5 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +5 -5
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +2 -2
- package/dist/drizzle/index.d.ts +2 -2
- package/dist/drizzle/index.js +2 -2
- package/dist/dynamodb/index.d.cts +2 -2
- package/dist/dynamodb/index.d.ts +2 -2
- package/dist/index.cjs +46 -141
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/schema/index.cjs +5 -5
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/secrets/index.cjs +46 -141
- package/dist/secrets/index.cjs.map +1 -1
- package/dist/secrets/index.d.cts +1 -1
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/index.js +4 -4
- package/dist/supabase/index.cjs +2 -2
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +2 -2
- package/dist/supabase/index.d.ts +2 -2
- package/dist/supabase/index.js +2 -2
- package/dist/{types-public-0CzBV45X.d.cts → types-public-Wj6tB_ux.d.cts} +47 -26
- package/dist/{types-public-0CzBV45X.d.ts → types-public-Wj6tB_ux.d.ts} +47 -26
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/dist/types-public.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-JLI27P46.js.map +0 -1
- package/dist/chunk-MW6D52V2.js.map +0 -1
- package/dist/chunk-SUYMGQBY.js.map +0 -1
- package/dist/chunk-TBAIVO6T.js.map +0 -1
|
@@ -5,15 +5,9 @@ function encryptedToPgComposite(obj) {
|
|
|
5
5
|
};
|
|
6
6
|
}
|
|
7
7
|
function encryptedToCompositeLiteral(obj) {
|
|
8
|
-
if (obj === null) {
|
|
9
|
-
throw new Error("encryptedToCompositeLiteral: obj cannot be null");
|
|
10
|
-
}
|
|
11
8
|
return `(${JSON.stringify(JSON.stringify(obj))})`;
|
|
12
9
|
}
|
|
13
10
|
function encryptedToEscapedCompositeLiteral(obj) {
|
|
14
|
-
if (obj === null) {
|
|
15
|
-
throw new Error("encryptedToEscapedCompositeLiteral: obj cannot be null");
|
|
16
|
-
}
|
|
17
11
|
return JSON.stringify(encryptedToCompositeLiteral(obj));
|
|
18
12
|
}
|
|
19
13
|
function formatEncryptedResult(encrypted, returnType) {
|
|
@@ -64,4 +58,4 @@ export {
|
|
|
64
58
|
toFfiKeysetIdentifier,
|
|
65
59
|
isEncryptedPayload
|
|
66
60
|
};
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-4RNBI3UH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/encryption/helpers/index.ts"],"sourcesContent":["import type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types'\nimport type {\n Encrypted as CipherStashEncrypted,\n KeysetIdentifier as KeysetIdentifierFfi,\n} from '@cipherstash/protect-ffi'\n\nexport type EncryptedPgComposite = {\n data: Encrypted\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite type.\n * Use this when inserting data via Supabase or similar clients.\n */\nexport function encryptedToPgComposite(obj: Encrypted): EncryptedPgComposite {\n return {\n data: obj,\n }\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite literal string.\n * Use this when querying with `.eq()` or similar equality operations in Supabase.\n *\n * @example\n * ```typescript\n * const literal = encryptedToCompositeLiteral(encrypted)\n * await supabase.from('table').select().eq('column', literal)\n * ```\n */\nexport function encryptedToCompositeLiteral(obj: CipherStashEncrypted): string {\n return `(${JSON.stringify(JSON.stringify(obj))})`\n}\n\n/**\n * Helper function to transform an encrypted payload into an escaped PostgreSQL composite literal string.\n * Use this when you need the composite literal format to be escaped as a string value.\n *\n * @example\n * ```typescript\n * const escapedLiteral = encryptedToEscapedCompositeLiteral(encrypted)\n * ```\n */\nexport function encryptedToEscapedCompositeLiteral(\n obj: CipherStashEncrypted,\n): string {\n return JSON.stringify(encryptedToCompositeLiteral(obj))\n}\n\n/**\n * Format an encrypted result based on the requested return type.\n *\n * - `'composite-literal'` → PostgreSQL composite literal string `(\"json\")`\n * - `'escaped-composite-literal'` → escaped variant `\"(\\\"json\\\")\"`\n * - default (`'eql'` or omitted) → raw encrypted object\n */\nexport function formatEncryptedResult(\n encrypted: CipherStashEncrypted,\n returnType?: string,\n): EncryptedQueryResult {\n if (returnType === 'composite-literal') {\n return encryptedToCompositeLiteral(encrypted)\n }\n if (returnType === 'escaped-composite-literal') {\n return encryptedToEscapedCompositeLiteral(encrypted)\n }\n return encrypted\n}\n\n/**\n * Helper function to transform a model's encrypted fields into PostgreSQL composite types\n */\nexport function modelToEncryptedPgComposites<T extends Record<string, unknown>>(\n model: T,\n): T {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (isEncryptedPayload(value)) {\n result[key] = encryptedToPgComposite(value)\n } else {\n result[key] = value\n }\n }\n\n return result as T\n}\n\n/**\n * Helper function to transform multiple models' encrypted fields into PostgreSQL composite types\n */\nexport function bulkModelsToEncryptedPgComposites<\n T extends Record<string, unknown>,\n>(models: T[]): T[] {\n return models.map((model) => modelToEncryptedPgComposites(model))\n}\n\nexport function toFfiKeysetIdentifier(\n keyset: KeysetIdentifier | undefined,\n): KeysetIdentifierFfi | undefined {\n if (!keyset) return undefined\n\n if ('name' in keyset) {\n return { Name: keyset.name }\n }\n\n return { Uuid: keyset.id }\n}\n\n/**\n * Helper function to check if a value is an encrypted payload\n */\nexport function isEncryptedPayload(value: unknown): value is Encrypted {\n if (value === null) return false\n if (typeof value !== 'object') return false\n\n const obj = value as Record<string, unknown>\n\n // Must have version field (number)\n if (!('v' in obj) || typeof obj.v !== 'number') return false\n\n // Must have index field (object)\n if (!('i' in obj) || typeof obj.i !== 'object') return false\n\n // Must have either ciphertext (c) or searchable vector (sv)\n if (!('c' in obj) && !('sv' in obj)) return false\n\n return true\n}\n\nexport {\n toJsonPath,\n buildNestedObject,\n parseJsonbPath,\n} from './jsonb'\n"],"mappings":";AAcO,SAAS,uBAAuB,KAAsC;AAC3E,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAYO,SAAS,4BAA4B,KAAmC;AAC7E,SAAO,IAAI,KAAK,UAAU,KAAK,UAAU,GAAG,CAAC,CAAC;AAChD;AAWO,SAAS,mCACd,KACQ;AACR,SAAO,KAAK,UAAU,4BAA4B,GAAG,CAAC;AACxD;AASO,SAAS,sBACd,WACA,YACsB;AACtB,MAAI,eAAe,qBAAqB;AACtC,WAAO,4BAA4B,SAAS;AAAA,EAC9C;AACA,MAAI,eAAe,6BAA6B;AAC9C,WAAO,mCAAmC,SAAS;AAAA,EACrD;AACA,SAAO;AACT;AAKO,SAAS,6BACd,OACG;AACH,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAO,GAAG,IAAI,uBAAuB,KAAK;AAAA,IAC5C,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kCAEd,QAAkB;AAClB,SAAO,OAAO,IAAI,CAAC,UAAU,6BAA6B,KAAK,CAAC;AAClE;AAEO,SAAS,sBACd,QACiC;AACjC,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,UAAU,QAAQ;AACpB,WAAO,EAAE,MAAM,OAAO,KAAK;AAAA,EAC7B;AAEA,SAAO,EAAE,MAAM,OAAO,GAAG;AAC3B;AAKO,SAAS,mBAAmB,OAAoC;AACrE,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,QAAM,MAAM;AAGZ,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,EAAE,QAAQ,KAAM,QAAO;AAE5C,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n EncryptedColumn,\n EncryptedTable,\n EncryptedTableColumn,\n EncryptedField,\n} from '@/schema'\nimport type { LoggingConfig } from '@/utils/logger'\nimport type {\n Encrypted as CipherStashEncrypted,\n JsPlaintext,\n QueryOpName,\n newClient,\n} from '@cipherstash/protect-ffi'\n\n// ---------------------------------------------------------------------------\n// Branded type utilities\n// ---------------------------------------------------------------------------\n\n/** Brand symbol for nominal typing */\ndeclare const __brand: unique symbol\n\n/** Creates a branded type that is structurally incompatible with the base type */\ntype Brand<T, B extends string> = T & { readonly [__brand]: B }\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\nexport type Client = Awaited<ReturnType<typeof newClient>> | undefined\n\n/** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */\nexport type EncryptedValue = Brand<CipherStashEncrypted, 'encrypted'>\n\n/** Structural type representing encrypted data. See also `EncryptedValue` for branded nominal typing. */\nexport type Encrypted = CipherStashEncrypted\n\n// ---------------------------------------------------------------------------\n// Client configuration\n// ---------------------------------------------------------------------------\n\nexport type KeysetIdentifier = { name: string } | { id: string }\n\nexport type ClientConfig = {\n /**\n * The CipherStash workspace CRN (Cloud Resource Name).\n * Format: `crn:<region>.aws:<workspace-id>`.\n * Can also be set via the `CS_WORKSPACE_CRN` environment variable.\n * If omitted, the SDK reads from the environment or TOML config files.\n */\n workspaceCrn?: string\n\n /**\n * The API access key used for authenticating with the CipherStash API.\n * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.\n * Obtain this from the CipherStash dashboard after creating a workspace.\n */\n accessKey?: string\n\n /**\n * The client identifier used to authenticate with CipherStash services.\n * Can also be set via the `CS_CLIENT_ID` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientId?: string\n\n /**\n * The client key material used in combination with ZeroKMS for encryption operations.\n * Can also be set via the `CS_CLIENT_KEY` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientKey?: string\n\n /**\n * An optional keyset identifier for multi-tenant encryption.\n * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.\n * Specify by name (`{ name: \"tenant-a\" }`) or UUID (`{ id: \"...\" }`).\n * Keysets are created and managed in the CipherStash dashboard.\n */\n keyset?: KeysetIdentifier\n}\n\ntype AtLeastOneCsTable<T> = [T, ...T[]]\n\nexport type EncryptionClientConfig = {\n schemas: AtLeastOneCsTable<EncryptedTable<EncryptedTableColumn>>\n config?: ClientConfig\n logging?: LoggingConfig\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt operation options and results\n// ---------------------------------------------------------------------------\n\n/**\n * Options for single-value encrypt operations.\n * Use a column from your table schema (from {@link encryptedColumn}) or a nested\n * field (from {@link encryptedField}) as the target for encryption.\n */\nexport type EncryptOptions = {\n /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */\n column: EncryptedColumn | EncryptedField\n table: EncryptedTable<EncryptedTableColumn>\n}\n\n/** Format for encrypted query/search term return values */\nexport type EncryptedReturnType =\n | 'eql'\n | 'composite-literal'\n | 'escaped-composite-literal'\n\nexport type SearchTerm = {\n value: JsPlaintext\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n returnType?: EncryptedReturnType\n}\n\n/** Encrypted search term result: EQL object or composite literal string */\nexport type EncryptedSearchTerm = Encrypted | string\n\n/** Result of encryptQuery (single or batch): EQL or composite literal string */\nexport type EncryptedQueryResult = Encrypted | string\n\n// ---------------------------------------------------------------------------\n// Model field types (encrypted vs decrypted views)\n// ---------------------------------------------------------------------------\n\nexport type EncryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K]\n}\n\nexport type OtherFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K]\n}\n\nexport type DecryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]:\n null extends T[K] ? string | null : string\n}\n\n/** Model with encrypted fields replaced by plaintext (decrypted) values */\nexport type Decrypted<T> = OtherFields<T> & DecryptedFields<T>\n\n/**\n * Maps a plaintext model type to its encrypted form using the table schema.\n *\n * Fields whose keys match columns defined in `S` become `Encrypted`;\n * all other fields retain their original types from `T`.\n *\n * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an\n * explicit `<User>` type argument without specifying `S`), the type degrades\n * gracefully to `T` — preserving backward compatibility.\n *\n * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)\n * @typeParam S - The table schema column definition, inferred from the `table` argument\n *\n * @example\n * ```typescript\n * type User = { id: string; email: string }\n * // With a schema that defines `email`:\n * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>\n * // => { id: string; email: Encrypted }\n * ```\n */\nexport type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {\n [K in keyof T]: [K] extends [keyof S]\n ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField]\n ? null extends T[K] ? Encrypted | null : Encrypted\n : T[K]\n : T[K]\n}\n\n// ---------------------------------------------------------------------------\n// Bulk operations\n// ---------------------------------------------------------------------------\n\nexport type BulkEncryptPayload = Array<{\n id?: string\n plaintext: JsPlaintext\n}>\n\nexport type BulkEncryptedData = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptPayload = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptedData = Array<DecryptionResult<JsPlaintext>>\n\ntype DecryptionSuccess<T> = { error?: never; data: T; id?: string }\ntype DecryptionError<T> = { error: T; id?: string; data?: never }\n\n/**\n * Result type for individual items in bulk decrypt operations.\n * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations\n * can have per-item failures.\n */\nexport type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>\n\n// ---------------------------------------------------------------------------\n// Query types (for searchable encryption / encryptQuery)\n// ---------------------------------------------------------------------------\n\n/**\n * User-facing query type names for encrypting query values.\n *\n * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/exact)\n * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/match)\n * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/platform/searchable-encryption/supported-queries/range)\n * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)\n * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)\n * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)\n */\nexport type QueryTypeName =\n | 'orderAndRange'\n | 'freeTextSearch'\n | 'equality'\n | 'steVecSelector'\n | 'steVecTerm'\n | 'searchableJson'\n\n/** @internal */\nexport type FfiIndexTypeName = 'ore' | 'match' | 'unique' | 'ste_vec'\n\nexport const queryTypes = {\n orderAndRange: 'orderAndRange',\n freeTextSearch: 'freeTextSearch',\n equality: 'equality',\n steVecSelector: 'steVecSelector',\n steVecTerm: 'steVecTerm',\n searchableJson: 'searchableJson',\n} as const satisfies Record<string, QueryTypeName>\n\n/** @internal */\nexport const queryTypeToFfi: Record<QueryTypeName, FfiIndexTypeName> = {\n orderAndRange: 'ore',\n freeTextSearch: 'match',\n equality: 'unique',\n steVecSelector: 'ste_vec',\n steVecTerm: 'ste_vec',\n searchableJson: 'ste_vec',\n}\n\n/** @internal */\nexport const queryTypeToQueryOp: Partial<Record<QueryTypeName, QueryOpName>> = {\n steVecSelector: 'ste_vec_selector',\n steVecTerm: 'ste_vec_term',\n}\n\n/** @internal */\nexport type QueryTermBase = {\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n queryType?: QueryTypeName\n returnType?: EncryptedReturnType\n}\n\nexport type EncryptQueryOptions = QueryTermBase\n\nexport type ScalarQueryTerm = QueryTermBase & {\n value: JsPlaintext\n}\n"],"mappings":";AA4NO,IAAM,aAAa;AAAA,EACxB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAGO,IAAM,iBAA0D;AAAA,EACrE,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAGO,IAAM,qBAAkE;AAAA,EAC7E,gBAAgB;AAAA,EAChB,YAAY;AACd;","names":[]}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
formatEncryptedResult,
|
|
3
3
|
isEncryptedPayload,
|
|
4
4
|
toFfiKeysetIdentifier
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4RNBI3UH.js";
|
|
6
6
|
import {
|
|
7
7
|
queryTypeToFfi,
|
|
8
8
|
queryTypeToQueryOp
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KOU2MHXJ.js";
|
|
10
10
|
import {
|
|
11
11
|
EncryptionErrorTypes,
|
|
12
12
|
createRequestLogger,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
buildEncryptConfig,
|
|
19
19
|
encryptConfigSchema
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-Y35W4WFN.js";
|
|
21
21
|
|
|
22
22
|
// src/encryption/index.ts
|
|
23
23
|
import { withResult as withResult11 } from "@byteslice/result";
|
|
@@ -167,18 +167,6 @@ var EncryptionOperation = class {
|
|
|
167
167
|
};
|
|
168
168
|
|
|
169
169
|
// src/encryption/operations/batch-encrypt-query.ts
|
|
170
|
-
function filterNullTerms(terms) {
|
|
171
|
-
const nullIndices = /* @__PURE__ */ new Set();
|
|
172
|
-
const nonNullTerms = [];
|
|
173
|
-
terms.forEach((term, index) => {
|
|
174
|
-
if (term.value === null || term.value === void 0) {
|
|
175
|
-
nullIndices.add(index);
|
|
176
|
-
} else {
|
|
177
|
-
nonNullTerms.push({ term, originalIndex: index });
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
return { nullIndices, nonNullTerms };
|
|
181
|
-
}
|
|
182
170
|
function buildQueryPayload(term, lockContext) {
|
|
183
171
|
assertValidNumericValue(term.value);
|
|
184
172
|
const { indexType, queryOp } = resolveIndexType(
|
|
@@ -199,13 +187,10 @@ function buildQueryPayload(term, lockContext) {
|
|
|
199
187
|
}
|
|
200
188
|
return payload;
|
|
201
189
|
}
|
|
202
|
-
function assembleResults(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
results[originalIndex] = formatEncryptedResult(encrypted, term.returnType);
|
|
207
|
-
});
|
|
208
|
-
return results;
|
|
190
|
+
function assembleResults(terms, encryptedValues) {
|
|
191
|
+
return terms.map(
|
|
192
|
+
(term, i) => formatEncryptedResult(encryptedValues[i], term.returnType)
|
|
193
|
+
);
|
|
209
194
|
}
|
|
210
195
|
var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
211
196
|
constructor(client, terms) {
|
|
@@ -232,23 +217,18 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
232
217
|
log.emit();
|
|
233
218
|
return { data: [] };
|
|
234
219
|
}
|
|
235
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
236
|
-
if (nonNullTerms.length === 0) {
|
|
237
|
-
log.emit();
|
|
238
|
-
return { data: this.terms.map(() => null) };
|
|
239
|
-
}
|
|
240
220
|
const result = await withResult(
|
|
241
221
|
async () => {
|
|
242
222
|
if (!this.client) throw noClientError();
|
|
243
223
|
const { metadata } = this.getAuditData();
|
|
244
|
-
const queries =
|
|
245
|
-
(
|
|
224
|
+
const queries = this.terms.map(
|
|
225
|
+
(term) => buildQueryPayload(term)
|
|
246
226
|
);
|
|
247
227
|
const encrypted = await ffiEncryptQueryBulk(this.client, {
|
|
248
228
|
queries,
|
|
249
229
|
unverifiedContext: metadata
|
|
250
230
|
});
|
|
251
|
-
return assembleResults(this.terms
|
|
231
|
+
return assembleResults(this.terms, encrypted);
|
|
252
232
|
},
|
|
253
233
|
(error) => {
|
|
254
234
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -282,11 +262,6 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
282
262
|
log.emit();
|
|
283
263
|
return { data: [] };
|
|
284
264
|
}
|
|
285
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
286
|
-
if (nonNullTerms.length === 0) {
|
|
287
|
-
log.emit();
|
|
288
|
-
return { data: this.terms.map(() => null) };
|
|
289
|
-
}
|
|
290
265
|
const lockContextResult = await this.lockContext.getLockContext();
|
|
291
266
|
if (lockContextResult.failure) {
|
|
292
267
|
log.emit();
|
|
@@ -297,15 +272,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
297
272
|
async () => {
|
|
298
273
|
if (!this.client) throw noClientError();
|
|
299
274
|
const { metadata } = this.getAuditData();
|
|
300
|
-
const queries =
|
|
301
|
-
(
|
|
275
|
+
const queries = this.terms.map(
|
|
276
|
+
(term) => buildQueryPayload(term, context)
|
|
302
277
|
);
|
|
303
278
|
const encrypted = await ffiEncryptQueryBulk(this.client, {
|
|
304
279
|
queries,
|
|
305
280
|
serviceToken: ctsToken,
|
|
306
281
|
unverifiedContext: metadata
|
|
307
282
|
});
|
|
308
|
-
return assembleResults(this.terms
|
|
283
|
+
return assembleResults(this.terms, encrypted);
|
|
309
284
|
},
|
|
310
285
|
(error) => {
|
|
311
286
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -327,42 +302,25 @@ import {
|
|
|
327
302
|
decryptBulkFallible
|
|
328
303
|
} from "@cipherstash/protect-ffi";
|
|
329
304
|
var createDecryptPayloads = (encryptedPayloads, lockContext) => {
|
|
330
|
-
return encryptedPayloads.map((
|
|
305
|
+
return encryptedPayloads.map(({ id, data }) => ({
|
|
331
306
|
id,
|
|
332
307
|
ciphertext: data,
|
|
333
|
-
originalIndex,
|
|
334
308
|
...lockContext && { lockContext }
|
|
335
309
|
}));
|
|
336
310
|
};
|
|
337
|
-
var createNullResult = (encryptedPayloads) => {
|
|
338
|
-
return encryptedPayloads.map(({ id }) => ({
|
|
339
|
-
id,
|
|
340
|
-
data: null
|
|
341
|
-
}));
|
|
342
|
-
};
|
|
343
311
|
var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const decryptResult = decryptedData[decryptedIndex];
|
|
351
|
-
if ("error" in decryptResult) {
|
|
352
|
-
result[i] = {
|
|
353
|
-
id: encryptedPayloads[i].id,
|
|
354
|
-
error: decryptResult.error
|
|
355
|
-
};
|
|
356
|
-
} else {
|
|
357
|
-
result[i] = {
|
|
358
|
-
id: encryptedPayloads[i].id,
|
|
359
|
-
data: decryptResult.data
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
decryptedIndex++;
|
|
312
|
+
return decryptedData.map((decryptResult, i) => {
|
|
313
|
+
if ("error" in decryptResult) {
|
|
314
|
+
return {
|
|
315
|
+
id: encryptedPayloads[i].id,
|
|
316
|
+
error: decryptResult.error
|
|
317
|
+
};
|
|
363
318
|
}
|
|
364
|
-
|
|
365
|
-
|
|
319
|
+
return {
|
|
320
|
+
id: encryptedPayloads[i].id,
|
|
321
|
+
data: decryptResult.data
|
|
322
|
+
};
|
|
323
|
+
});
|
|
366
324
|
};
|
|
367
325
|
var BulkDecryptOperation = class extends EncryptionOperation {
|
|
368
326
|
client;
|
|
@@ -387,13 +345,10 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
387
345
|
if (!this.client) throw noClientError();
|
|
388
346
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
389
347
|
return [];
|
|
390
|
-
const
|
|
391
|
-
if (nonNullPayloads.length === 0) {
|
|
392
|
-
return createNullResult(this.encryptedPayloads);
|
|
393
|
-
}
|
|
348
|
+
const payloads = createDecryptPayloads(this.encryptedPayloads);
|
|
394
349
|
const { metadata } = this.getAuditData();
|
|
395
350
|
const decryptedData = await decryptBulkFallible(this.client, {
|
|
396
|
-
ciphertexts:
|
|
351
|
+
ciphertexts: payloads,
|
|
397
352
|
unverifiedContext: metadata
|
|
398
353
|
});
|
|
399
354
|
return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
|
|
@@ -445,16 +400,13 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
445
400
|
if (context.failure) {
|
|
446
401
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
447
402
|
}
|
|
448
|
-
const
|
|
403
|
+
const payloads = createDecryptPayloads(
|
|
449
404
|
encryptedPayloads,
|
|
450
405
|
context.data.context
|
|
451
406
|
);
|
|
452
|
-
if (nonNullPayloads.length === 0) {
|
|
453
|
-
return createNullResult(encryptedPayloads);
|
|
454
|
-
}
|
|
455
407
|
const { metadata } = this.getAuditData();
|
|
456
408
|
const decryptedData = await decryptBulkFallible(client, {
|
|
457
|
-
ciphertexts:
|
|
409
|
+
ciphertexts: payloads,
|
|
458
410
|
serviceToken: context.data.ctsToken,
|
|
459
411
|
unverifiedContext: metadata
|
|
460
412
|
});
|
|
@@ -1096,34 +1048,14 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1096
1048
|
import { withResult as withResult4 } from "@byteslice/result";
|
|
1097
1049
|
import { encryptBulk as encryptBulk2 } from "@cipherstash/protect-ffi";
|
|
1098
1050
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
1099
|
-
return plaintexts.map((
|
|
1051
|
+
return plaintexts.map(({ id, plaintext }) => ({
|
|
1100
1052
|
id,
|
|
1101
1053
|
plaintext,
|
|
1102
1054
|
column: column.getName(),
|
|
1103
1055
|
table: table.tableName,
|
|
1104
|
-
originalIndex,
|
|
1105
1056
|
...lockContext && { lockContext }
|
|
1106
1057
|
}));
|
|
1107
1058
|
};
|
|
1108
|
-
var createNullResult2 = (plaintexts) => {
|
|
1109
|
-
return plaintexts.map(({ id }) => ({ id, data: null }));
|
|
1110
|
-
};
|
|
1111
|
-
var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
|
|
1112
|
-
const result = new Array(plaintexts.length);
|
|
1113
|
-
let encryptedIndex = 0;
|
|
1114
|
-
for (let i = 0; i < plaintexts.length; i++) {
|
|
1115
|
-
if (plaintexts[i].plaintext === null) {
|
|
1116
|
-
result[i] = { id: plaintexts[i].id, data: null };
|
|
1117
|
-
} else {
|
|
1118
|
-
result[i] = {
|
|
1119
|
-
id: plaintexts[i].id,
|
|
1120
|
-
data: encryptedData[encryptedIndex]
|
|
1121
|
-
};
|
|
1122
|
-
encryptedIndex++;
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
return result;
|
|
1126
|
-
};
|
|
1127
1059
|
var BulkEncryptOperation = class extends EncryptionOperation {
|
|
1128
1060
|
client;
|
|
1129
1061
|
plaintexts;
|
|
@@ -1156,20 +1088,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
1156
1088
|
if (!this.plaintexts || this.plaintexts.length === 0) {
|
|
1157
1089
|
return [];
|
|
1158
1090
|
}
|
|
1159
|
-
const
|
|
1091
|
+
const payloads = createEncryptPayloads(
|
|
1160
1092
|
this.plaintexts,
|
|
1161
1093
|
this.column,
|
|
1162
1094
|
this.table
|
|
1163
1095
|
);
|
|
1164
|
-
if (nonNullPayloads.length === 0) {
|
|
1165
|
-
return createNullResult2(this.plaintexts);
|
|
1166
|
-
}
|
|
1167
1096
|
const { metadata } = this.getAuditData();
|
|
1168
1097
|
const encryptedData = await encryptBulk2(this.client, {
|
|
1169
|
-
plaintexts:
|
|
1098
|
+
plaintexts: payloads,
|
|
1170
1099
|
unverifiedContext: metadata
|
|
1171
1100
|
});
|
|
1172
|
-
return
|
|
1101
|
+
return encryptedData.map((data, i) => ({
|
|
1102
|
+
id: this.plaintexts[i].id,
|
|
1103
|
+
data
|
|
1104
|
+
}));
|
|
1173
1105
|
},
|
|
1174
1106
|
(error) => {
|
|
1175
1107
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1226,22 +1158,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1226
1158
|
if (context.failure) {
|
|
1227
1159
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1228
1160
|
}
|
|
1229
|
-
const
|
|
1161
|
+
const payloads = createEncryptPayloads(
|
|
1230
1162
|
plaintexts,
|
|
1231
1163
|
column,
|
|
1232
1164
|
table,
|
|
1233
1165
|
context.data.context
|
|
1234
1166
|
);
|
|
1235
|
-
if (nonNullPayloads.length === 0) {
|
|
1236
|
-
return createNullResult2(plaintexts);
|
|
1237
|
-
}
|
|
1238
1167
|
const { metadata } = this.getAuditData();
|
|
1239
1168
|
const encryptedData = await encryptBulk2(client, {
|
|
1240
|
-
plaintexts:
|
|
1169
|
+
plaintexts: payloads,
|
|
1241
1170
|
serviceToken: context.data.ctsToken,
|
|
1242
1171
|
unverifiedContext: metadata
|
|
1243
1172
|
});
|
|
1244
|
-
return
|
|
1173
|
+
return encryptedData.map((data, i) => ({
|
|
1174
|
+
id: plaintexts[i].id,
|
|
1175
|
+
data
|
|
1176
|
+
}));
|
|
1245
1177
|
},
|
|
1246
1178
|
(error) => {
|
|
1247
1179
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1393,9 +1325,6 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
1393
1325
|
if (!this.client) {
|
|
1394
1326
|
throw noClientError();
|
|
1395
1327
|
}
|
|
1396
|
-
if (this.encryptedData === null) {
|
|
1397
|
-
return null;
|
|
1398
|
-
}
|
|
1399
1328
|
const { metadata } = this.getAuditData();
|
|
1400
1329
|
return await ffiDecrypt(this.client, {
|
|
1401
1330
|
ciphertext: this.encryptedData,
|
|
@@ -1446,9 +1375,6 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1446
1375
|
if (!client) {
|
|
1447
1376
|
throw noClientError();
|
|
1448
1377
|
}
|
|
1449
|
-
if (encryptedData === null) {
|
|
1450
|
-
return null;
|
|
1451
|
-
}
|
|
1452
1378
|
const { metadata } = this.getAuditData();
|
|
1453
1379
|
const context = await this.lockContext.getLockContext();
|
|
1454
1380
|
if (context.failure) {
|
|
@@ -1604,9 +1530,6 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
1604
1530
|
if (!this.client) {
|
|
1605
1531
|
throw noClientError();
|
|
1606
1532
|
}
|
|
1607
|
-
if (this.plaintext === null) {
|
|
1608
|
-
return null;
|
|
1609
|
-
}
|
|
1610
1533
|
if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
|
|
1611
1534
|
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
1612
1535
|
}
|
|
@@ -1668,9 +1591,6 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1668
1591
|
if (!client) {
|
|
1669
1592
|
throw noClientError();
|
|
1670
1593
|
}
|
|
1671
|
-
if (plaintext === null) {
|
|
1672
|
-
return null;
|
|
1673
|
-
}
|
|
1674
1594
|
const { metadata } = this.getAuditData();
|
|
1675
1595
|
const context = await this.lockContext.getLockContext();
|
|
1676
1596
|
if (context.failure) {
|
|
@@ -1836,10 +1756,6 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
1836
1756
|
queryType: this.opts.queryType,
|
|
1837
1757
|
lockContext: false
|
|
1838
1758
|
});
|
|
1839
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
1840
|
-
log.emit();
|
|
1841
|
-
return { data: null };
|
|
1842
|
-
}
|
|
1843
1759
|
const validationError = validateNumericValue(this.plaintext);
|
|
1844
1760
|
if (validationError?.failure) {
|
|
1845
1761
|
log.emit();
|
|
@@ -1903,10 +1819,6 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1903
1819
|
queryType: this.opts.queryType,
|
|
1904
1820
|
lockContext: true
|
|
1905
1821
|
});
|
|
1906
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
1907
|
-
log.emit();
|
|
1908
|
-
return { data: null };
|
|
1909
|
-
}
|
|
1910
1822
|
const validationError = validateNumericValue(this.plaintext);
|
|
1911
1823
|
if (validationError?.failure) {
|
|
1912
1824
|
log.emit();
|
|
@@ -2011,7 +1923,7 @@ var EncryptionClient = class {
|
|
|
2011
1923
|
/**
|
|
2012
1924
|
* Encrypt a value - returns a promise which resolves to an encrypted value.
|
|
2013
1925
|
*
|
|
2014
|
-
* @param plaintext - The plaintext value to be encrypted.
|
|
1926
|
+
* @param plaintext - The plaintext value to be encrypted.
|
|
2015
1927
|
* @param opts - Options specifying the column (or nested field) and table for encryption. See {@link EncryptOptions}.
|
|
2016
1928
|
* @returns An EncryptOperation that can be awaited or chained with additional methods.
|
|
2017
1929
|
*
|
|
@@ -2312,7 +2224,7 @@ var EncryptionClient = class {
|
|
|
2312
2224
|
*
|
|
2313
2225
|
* Each value is encrypted with its own unique key via a single call to ZeroKMS.
|
|
2314
2226
|
* Values can include optional `id` fields for correlating results back to
|
|
2315
|
-
* your application data.
|
|
2227
|
+
* your application data.
|
|
2316
2228
|
*
|
|
2317
2229
|
* @param plaintexts - An array of objects with `plaintext` (and optional `id`) fields.
|
|
2318
2230
|
* @param opts - Options specifying the target column (or nested {@link encryptedField}) and table. See {@link EncryptOptions}.
|
|
@@ -2333,7 +2245,6 @@ var EncryptionClient = class {
|
|
|
2333
2245
|
* [
|
|
2334
2246
|
* { id: "u1", plaintext: "alice@example.com" },
|
|
2335
2247
|
* { id: "u2", plaintext: "bob@example.com" },
|
|
2336
|
-
* { id: "u3", plaintext: null },
|
|
2337
2248
|
* ],
|
|
2338
2249
|
* { column: users.email, table: users },
|
|
2339
2250
|
* )
|
|
@@ -2423,4 +2334,4 @@ var Encryption = async (config) => {
|
|
|
2423
2334
|
export {
|
|
2424
2335
|
Encryption
|
|
2425
2336
|
};
|
|
2426
|
-
//# sourceMappingURL=chunk-
|
|
2337
|
+
//# sourceMappingURL=chunk-WUZGKTMG.js.map
|