@cipherstash/stack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE.md +21 -0
- package/README.md +670 -0
- package/dist/bin/stash.js +5049 -0
- package/dist/bin/stash.js.map +1 -0
- package/dist/chunk-2GZMIJFO.js +2400 -0
- package/dist/chunk-2GZMIJFO.js.map +1 -0
- package/dist/chunk-5DCT6YU2.js +138 -0
- package/dist/chunk-5DCT6YU2.js.map +1 -0
- package/dist/chunk-7XRPN2KX.js +336 -0
- package/dist/chunk-7XRPN2KX.js.map +1 -0
- package/dist/chunk-SJ7JO4ME.js +28 -0
- package/dist/chunk-SJ7JO4ME.js.map +1 -0
- package/dist/chunk-SUYMGQBY.js +67 -0
- package/dist/chunk-SUYMGQBY.js.map +1 -0
- package/dist/client-BxJG56Ey.d.cts +647 -0
- package/dist/client-DtGq9dJp.d.ts +647 -0
- package/dist/client.cjs +347 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +7 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +11 -0
- package/dist/client.js.map +1 -0
- package/dist/drizzle/index.cjs +1528 -0
- package/dist/drizzle/index.cjs.map +1 -0
- package/dist/drizzle/index.d.cts +350 -0
- package/dist/drizzle/index.d.ts +350 -0
- package/dist/drizzle/index.js +1212 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/dynamodb/index.cjs +382 -0
- package/dist/dynamodb/index.cjs.map +1 -0
- package/dist/dynamodb/index.d.cts +125 -0
- package/dist/dynamodb/index.d.ts +125 -0
- package/dist/dynamodb/index.js +355 -0
- package/dist/dynamodb/index.js.map +1 -0
- package/dist/identity/index.cjs +271 -0
- package/dist/identity/index.cjs.map +1 -0
- package/dist/identity/index.d.cts +3 -0
- package/dist/identity/index.d.ts +3 -0
- package/dist/identity/index.js +117 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/index-9-Ya3fDK.d.cts +169 -0
- package/dist/index-9-Ya3fDK.d.ts +169 -0
- package/dist/index.cjs +2915 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/schema/index.cjs +368 -0
- package/dist/schema/index.cjs.map +1 -0
- package/dist/schema/index.d.cts +4 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.js +23 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/secrets/index.cjs +3207 -0
- package/dist/secrets/index.cjs.map +1 -0
- package/dist/secrets/index.d.cts +227 -0
- package/dist/secrets/index.d.ts +227 -0
- package/dist/secrets/index.js +323 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/supabase/index.cjs +1113 -0
- package/dist/supabase/index.cjs.map +1 -0
- package/dist/supabase/index.d.cts +144 -0
- package/dist/supabase/index.d.ts +144 -0
- package/dist/supabase/index.js +864 -0
- package/dist/supabase/index.js.map +1 -0
- package/dist/types-public-BCj1L4fi.d.cts +1013 -0
- package/dist/types-public-BCj1L4fi.d.ts +1013 -0
- package/dist/types-public.cjs +40 -0
- package/dist/types-public.cjs.map +1 -0
- package/dist/types-public.d.cts +4 -0
- package/dist/types-public.d.ts +4 -0
- package/dist/types-public.js +7 -0
- package/dist/types-public.js.map +1 -0
- package/package.json +202 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/dynamodb/index.ts","../../src/dynamodb/operations/bulk-decrypt-models.ts","../../src/dynamodb/helpers.ts","../../src/dynamodb/operations/base-operation.ts","../../src/dynamodb/operations/bulk-encrypt-models.ts","../../src/dynamodb/operations/decrypt-model.ts","../../src/dynamodb/operations/encrypt-model.ts"],"sourcesContent":["import type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { EncryptedValue } from '@/types'\nimport { BulkDecryptModelsOperation } from './operations/bulk-decrypt-models'\nimport { BulkEncryptModelsOperation } from './operations/bulk-encrypt-models'\nimport { DecryptModelOperation } from './operations/decrypt-model'\nimport { EncryptModelOperation } from './operations/encrypt-model'\nimport type {\n EncryptedDynamoDBConfig,\n EncryptedDynamoDBInstance,\n} from './types'\n\n/**\n * Create an encrypted DynamoDB helper bound to an `EncryptionClient`.\n *\n * Returns an object with `encryptModel`, `decryptModel`, `bulkEncryptModels`,\n * and `bulkDecryptModels` methods that transparently encrypt/decrypt DynamoDB\n * items according to the provided table schema.\n *\n * @param config - Configuration containing the `encryptionClient` and optional\n * logging / error-handling callbacks.\n * @returns An {@link EncryptedDynamoDBInstance} with encrypt/decrypt operations.\n *\n * @example\n * ```typescript\n * import { Encryption } from \"@cipherstash/stack\"\n * import { encryptedDynamoDB } from \"@cipherstash/stack/dynamodb\"\n * import { encryptedTable, encryptedColumn } from \"@cipherstash/stack/schema\"\n *\n * const users = encryptedTable(\"users\", {\n * email: encryptedColumn(\"email\").equality(),\n * })\n *\n * const client = await Encryption({ schemas: [users] })\n * const dynamo = encryptedDynamoDB({ encryptionClient: client })\n *\n * const encrypted = await dynamo.encryptModel({ email: \"a@b.com\" }, users)\n * ```\n */\nexport function encryptedDynamoDB(\n config: EncryptedDynamoDBConfig,\n): EncryptedDynamoDBInstance {\n const { encryptionClient, options } = config\n\n return {\n encryptModel<T extends Record<string, unknown>>(\n item: T,\n table: ProtectTable<ProtectTableColumn>,\n ) {\n return new EncryptModelOperation<T>(\n encryptionClient,\n item,\n table,\n options,\n )\n },\n\n bulkEncryptModels<T extends Record<string, unknown>>(\n items: T[],\n table: ProtectTable<ProtectTableColumn>,\n ) {\n return new BulkEncryptModelsOperation<T>(\n encryptionClient,\n items,\n table,\n options,\n )\n },\n\n decryptModel<T extends Record<string, unknown>>(\n item: Record<string, EncryptedValue | unknown>,\n table: ProtectTable<ProtectTableColumn>,\n ) {\n return new DecryptModelOperation<T>(\n encryptionClient,\n item,\n table,\n options,\n )\n },\n\n bulkDecryptModels<T extends Record<string, unknown>>(\n items: Record<string, EncryptedValue | unknown>[],\n table: ProtectTable<ProtectTableColumn>,\n ) {\n return new BulkDecryptModelsOperation<T>(\n encryptionClient,\n items,\n table,\n options,\n )\n },\n }\n}\n\nexport type {\n EncryptedDynamoDBConfig,\n EncryptedDynamoDBError,\n EncryptedDynamoDBInstance,\n} from './types'\n","import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { Decrypted, EncryptedValue } from '@/types'\nimport { type Result, withResult } from '@byteslice/result'\nimport { handleError, toItemWithEqlPayloads } from '../helpers'\nimport type { EncryptedDynamoDBError } from '../types'\nimport {\n DynamoDBOperation,\n type DynamoDBOperationOptions,\n} from './base-operation'\n\nexport class BulkDecryptModelsOperation<\n T extends Record<string, unknown>,\n> extends DynamoDBOperation<Decrypted<T>[]> {\n private encryptionClient: EncryptionClient\n private items: Record<string, EncryptedValue | unknown>[]\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n encryptionClient: EncryptionClient,\n items: Record<string, EncryptedValue | unknown>[],\n table: ProtectTable<ProtectTableColumn>,\n options?: DynamoDBOperationOptions,\n ) {\n super(options)\n this.encryptionClient = encryptionClient\n this.items = items\n this.table = table\n }\n\n public async execute(): Promise<\n Result<Decrypted<T>[], EncryptedDynamoDBError>\n > {\n return await withResult(\n async () => {\n const itemsWithEqlPayloads = this.items.map((item) =>\n toItemWithEqlPayloads(item, this.table),\n )\n\n const decryptResult = await this.encryptionClient\n .bulkDecryptModels<T>(itemsWithEqlPayloads as T[])\n .audit(this.getAuditData())\n\n if (decryptResult.failure) {\n // Create an Error object that preserves the FFI error code\n // This is necessary because withResult's ensureError wraps non-Error objects\n const error = new Error(decryptResult.failure.message) as Error & {\n code?: string\n }\n error.code = decryptResult.failure.code\n throw error\n }\n\n return decryptResult.data\n },\n (error) =>\n handleError(error, 'bulkDecryptModels', {\n logger: this.logger,\n errorHandler: this.errorHandler,\n }),\n )\n }\n}\n","import type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { EncryptedValue } from '@/types'\nimport type { ProtectErrorCode } from '@cipherstash/protect-ffi'\nimport { ProtectError as FfiProtectError } from '@cipherstash/protect-ffi'\nimport type { EncryptedDynamoDBError } from './types'\n\nexport const ciphertextAttrSuffix = '__source'\nexport const searchTermAttrSuffix = '__hmac'\n\nexport class EncryptedDynamoDBErrorImpl\n extends Error\n implements EncryptedDynamoDBError\n{\n constructor(\n message: string,\n public code: ProtectErrorCode | 'DYNAMODB_ENCRYPTION_ERROR',\n public details?: Record<string, unknown>,\n ) {\n super(message)\n this.name = 'EncryptedDynamoDBError'\n }\n}\n\nexport function handleError(\n error: unknown,\n context: string,\n options?: {\n logger?: {\n error: (message: string, error: Error) => void\n }\n errorHandler?: (error: EncryptedDynamoDBError) => void\n },\n): EncryptedDynamoDBError {\n // Preserve FFI error code if available, otherwise use generic DynamoDB error code\n // Check for FfiProtectError instance or plain error objects with code property\n const errorObj = error as Record<string, unknown>\n const errorCode =\n error instanceof FfiProtectError\n ? error.code\n : errorObj &&\n typeof errorObj === 'object' &&\n 'code' in errorObj &&\n typeof errorObj.code === 'string'\n ? (errorObj.code as ProtectErrorCode)\n : 'DYNAMODB_ENCRYPTION_ERROR'\n\n const errorMessage =\n error instanceof Error\n ? error.message\n : errorObj && typeof errorObj.message === 'string'\n ? errorObj.message\n : String(error)\n\n const dynamoError = new EncryptedDynamoDBErrorImpl(errorMessage, errorCode, {\n context,\n })\n\n if (options?.errorHandler) {\n options.errorHandler(dynamoError)\n }\n\n if (options?.logger) {\n options.logger.error(`Error in ${context}`, dynamoError)\n }\n\n return dynamoError\n}\n\nexport function deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => deepClone(item)) as unknown as T\n }\n\n return Object.entries(obj as Record<string, unknown>).reduce(\n (acc, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: TODO later\n ...acc,\n [key]: deepClone(value),\n }),\n {} as T,\n )\n}\n\nexport function toEncryptedDynamoItem(\n encrypted: Record<string, unknown>,\n encryptedAttrs: string[],\n): Record<string, unknown> {\n function processValue(\n attrName: string,\n attrValue: unknown,\n isNested: boolean,\n ): Record<string, unknown> {\n if (attrValue === null || attrValue === undefined) {\n return { [attrName]: attrValue }\n }\n\n // Handle encrypted payload\n if (\n encryptedAttrs.includes(attrName) ||\n (isNested &&\n typeof attrValue === 'object' &&\n 'c' in (attrValue as object))\n ) {\n const encryptPayload = attrValue as EncryptedValue\n if (encryptPayload?.c) {\n const result: Record<string, unknown> = {}\n if (encryptPayload.hm) {\n result[`${attrName}${searchTermAttrSuffix}`] = encryptPayload.hm\n }\n result[`${attrName}${ciphertextAttrSuffix}`] = encryptPayload.c\n return result\n }\n\n if (encryptPayload?.sv) {\n const result: Record<string, unknown> = {}\n result[`${attrName}${ciphertextAttrSuffix}`] = encryptPayload.sv\n return result\n }\n }\n\n // Handle nested objects recursively\n if (typeof attrValue === 'object' && !Array.isArray(attrValue)) {\n const nestedResult = Object.entries(\n attrValue as Record<string, unknown>,\n ).reduce(\n (acc, [key, val]) => {\n const processed = processValue(key, val, true)\n return Object.assign({}, acc, processed)\n },\n {} as Record<string, unknown>,\n )\n return { [attrName]: nestedResult }\n }\n\n // Handle non-encrypted values\n return { [attrName]: attrValue }\n }\n\n return Object.entries(encrypted).reduce(\n (putItem, [attrName, attrValue]) => {\n const processed = processValue(attrName, attrValue, false)\n return Object.assign({}, putItem, processed)\n },\n {} as Record<string, unknown>,\n )\n}\n\nexport function toItemWithEqlPayloads(\n decrypted: Record<string, EncryptedValue | unknown>,\n encryptionSchema: ProtectTable<ProtectTableColumn>,\n): Record<string, unknown> {\n function processValue(\n attrName: string,\n attrValue: unknown,\n isNested: boolean,\n ): Record<string, unknown> {\n if (attrValue === null || attrValue === undefined) {\n return { [attrName]: attrValue }\n }\n\n // Skip HMAC fields\n if (attrName.endsWith(searchTermAttrSuffix)) {\n return {}\n }\n\n const encryptConfig = encryptionSchema.build()\n const encryptedAttrs = Object.keys(encryptConfig.columns)\n const columnName = attrName.slice(0, -ciphertextAttrSuffix.length)\n\n // Handle encrypted payload\n if (\n attrName.endsWith(ciphertextAttrSuffix) &&\n (encryptedAttrs.includes(columnName) || isNested)\n ) {\n const i = { c: columnName, t: encryptConfig.tableName }\n const v = 2\n\n // Nested values are not searchable, so we can just return the standard EQL payload.\n // Worth noting, that encryptConfig.columns[columnName] will be undefined if isNested is true.\n if (\n !isNested &&\n encryptConfig.columns[columnName].cast_as === 'json' &&\n encryptConfig.columns[columnName].indexes.ste_vec\n ) {\n return {\n [columnName]: {\n i,\n v,\n k: 'sv',\n sv: attrValue,\n },\n }\n }\n\n return {\n [columnName]: {\n i,\n v,\n k: 'ct',\n c: attrValue,\n },\n }\n }\n\n // Handle nested objects recursively\n if (typeof attrValue === 'object' && !Array.isArray(attrValue)) {\n const nestedResult = Object.entries(\n attrValue as Record<string, unknown>,\n ).reduce(\n (acc, [key, val]) => {\n const processed = processValue(key, val, true)\n return Object.assign({}, acc, processed)\n },\n {} as Record<string, unknown>,\n )\n return { [attrName]: nestedResult }\n }\n\n // Handle non-encrypted values\n return { [attrName]: attrValue }\n }\n\n return Object.entries(decrypted).reduce(\n (formattedItem, [attrName, attrValue]) => {\n const processed = processValue(attrName, attrValue, false)\n return Object.assign({}, formattedItem, processed)\n },\n {} as Record<string, unknown>,\n )\n}\n","import type { Result } from '@byteslice/result'\nimport type { EncryptedDynamoDBError } from '../types'\n\nexport type AuditConfig = {\n metadata?: Record<string, unknown>\n}\n\nexport type AuditData = {\n metadata?: Record<string, unknown>\n}\n\nexport type DynamoDBOperationOptions = {\n logger?: {\n error: (message: string, error: Error) => void\n }\n errorHandler?: (error: EncryptedDynamoDBError) => void\n}\n\nexport abstract class DynamoDBOperation<T> {\n protected auditMetadata?: Record<string, unknown>\n protected logger?: DynamoDBOperationOptions['logger']\n protected errorHandler?: DynamoDBOperationOptions['errorHandler']\n\n constructor(options?: DynamoDBOperationOptions) {\n this.logger = options?.logger\n this.errorHandler = options?.errorHandler\n }\n\n /**\n * Attach audit metadata to this operation. Can be chained.\n */\n audit(config: AuditConfig): this {\n this.auditMetadata = config.metadata\n return this\n }\n\n /**\n * Get the audit metadata for this operation.\n */\n protected getAuditData(): AuditData {\n return {\n metadata: this.auditMetadata,\n }\n }\n\n /**\n * Execute the operation and return a Result\n */\n abstract execute(): Promise<Result<T, EncryptedDynamoDBError>>\n\n /**\n * Make the operation thenable\n */\n public then<TResult1 = Result<T, EncryptedDynamoDBError>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Result<T, EncryptedDynamoDBError>,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected)\n }\n}\n","import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport { type Result, withResult } from '@byteslice/result'\nimport { deepClone, handleError, toEncryptedDynamoItem } from '../helpers'\nimport type { EncryptedDynamoDBError } from '../types'\nimport {\n DynamoDBOperation,\n type DynamoDBOperationOptions,\n} from './base-operation'\n\nexport class BulkEncryptModelsOperation<\n T extends Record<string, unknown>,\n> extends DynamoDBOperation<T[]> {\n private encryptionClient: EncryptionClient\n private items: T[]\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n encryptionClient: EncryptionClient,\n items: T[],\n table: ProtectTable<ProtectTableColumn>,\n options?: DynamoDBOperationOptions,\n ) {\n super(options)\n this.encryptionClient = encryptionClient\n this.items = items\n this.table = table\n }\n\n public async execute(): Promise<Result<T[], EncryptedDynamoDBError>> {\n return await withResult(\n async () => {\n const encryptResult = await this.encryptionClient\n .bulkEncryptModels(\n this.items.map((item) => deepClone(item)),\n this.table,\n )\n .audit(this.getAuditData())\n\n if (encryptResult.failure) {\n // Create an Error object that preserves the FFI error code\n // This is necessary because withResult's ensureError wraps non-Error objects\n const error = new Error(encryptResult.failure.message) as Error & {\n code?: string\n }\n error.code = encryptResult.failure.code\n throw error\n }\n\n const data = encryptResult.data.map((item) => deepClone(item))\n const encryptedAttrs = Object.keys(this.table.build().columns)\n\n return data.map(\n (encrypted) => toEncryptedDynamoItem(encrypted, encryptedAttrs) as T,\n )\n },\n (error) =>\n handleError(error, 'bulkEncryptModels', {\n logger: this.logger,\n errorHandler: this.errorHandler,\n }),\n )\n }\n}\n","import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport type { Decrypted, EncryptedValue } from '@/types'\nimport { type Result, withResult } from '@byteslice/result'\nimport { handleError, toItemWithEqlPayloads } from '../helpers'\nimport type { EncryptedDynamoDBError } from '../types'\nimport {\n DynamoDBOperation,\n type DynamoDBOperationOptions,\n} from './base-operation'\n\nexport class DecryptModelOperation<\n T extends Record<string, unknown>,\n> extends DynamoDBOperation<Decrypted<T>> {\n private encryptionClient: EncryptionClient\n private item: Record<string, EncryptedValue | unknown>\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n encryptionClient: EncryptionClient,\n item: Record<string, EncryptedValue | unknown>,\n table: ProtectTable<ProtectTableColumn>,\n options?: DynamoDBOperationOptions,\n ) {\n super(options)\n this.encryptionClient = encryptionClient\n this.item = item\n this.table = table\n }\n\n public async execute(): Promise<\n Result<Decrypted<T>, EncryptedDynamoDBError>\n > {\n return await withResult(\n async () => {\n const withEqlPayloads = toItemWithEqlPayloads(this.item, this.table)\n\n const decryptResult = await this.encryptionClient\n .decryptModel<T>(withEqlPayloads as T)\n .audit(this.getAuditData())\n\n if (decryptResult.failure) {\n // Create an Error object that preserves the FFI error code\n // This is necessary because withResult's ensureError wraps non-Error objects\n const error = new Error(decryptResult.failure.message) as Error & {\n code?: string\n }\n error.code = decryptResult.failure.code\n throw error\n }\n\n return decryptResult.data\n },\n (error) =>\n handleError(error, 'decryptModel', {\n logger: this.logger,\n errorHandler: this.errorHandler,\n }),\n )\n }\n}\n","import type { EncryptionClient } from '@/encryption/ffi'\nimport type { ProtectTable, ProtectTableColumn } from '@/schema'\nimport { type Result, withResult } from '@byteslice/result'\nimport { deepClone, handleError, toEncryptedDynamoItem } from '../helpers'\nimport type { EncryptedDynamoDBError } from '../types'\nimport {\n DynamoDBOperation,\n type DynamoDBOperationOptions,\n} from './base-operation'\n\nexport class EncryptModelOperation<\n T extends Record<string, unknown>,\n> extends DynamoDBOperation<T> {\n private encryptionClient: EncryptionClient\n private item: T\n private table: ProtectTable<ProtectTableColumn>\n\n constructor(\n encryptionClient: EncryptionClient,\n item: T,\n table: ProtectTable<ProtectTableColumn>,\n options?: DynamoDBOperationOptions,\n ) {\n super(options)\n this.encryptionClient = encryptionClient\n this.item = item\n this.table = table\n }\n\n public async execute(): Promise<Result<T, EncryptedDynamoDBError>> {\n return await withResult(\n async () => {\n const encryptResult = await this.encryptionClient\n .encryptModel(deepClone(this.item), this.table)\n .audit(this.getAuditData())\n\n if (encryptResult.failure) {\n // Create an Error object that preserves the FFI error code\n // This is necessary because withResult's ensureError wraps non-Error objects\n const error = new Error(encryptResult.failure.message) as Error & {\n code?: string\n }\n error.code = encryptResult.failure.code\n throw error\n }\n\n const data = deepClone(encryptResult.data)\n const encryptedAttrs = Object.keys(this.table.build().columns)\n\n return toEncryptedDynamoItem(data, encryptedAttrs) as T\n },\n (error) =>\n handleError(error, 'encryptModel', {\n logger: this.logger,\n errorHandler: this.errorHandler,\n }),\n )\n }\n}\n"],"mappings":"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","names":["FfiProtectError","import_result","import_result","import_result"]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { E as EncryptionClient } from '../client-BxJG56Ey.cjs';
|
|
2
|
+
import { D as Decrypted, i as EncryptedValue, d as ProtectTable, f as ProtectTableColumn } from '../types-public-BCj1L4fi.cjs';
|
|
3
|
+
import { ProtectErrorCode } from '@cipherstash/protect-ffi';
|
|
4
|
+
import { Result } from '@byteslice/result';
|
|
5
|
+
import '../index-9-Ya3fDK.cjs';
|
|
6
|
+
import 'zod';
|
|
7
|
+
import 'evlog';
|
|
8
|
+
|
|
9
|
+
type AuditConfig = {
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
type AuditData = {
|
|
13
|
+
metadata?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
type DynamoDBOperationOptions = {
|
|
16
|
+
logger?: {
|
|
17
|
+
error: (message: string, error: Error) => void;
|
|
18
|
+
};
|
|
19
|
+
errorHandler?: (error: EncryptedDynamoDBError) => void;
|
|
20
|
+
};
|
|
21
|
+
declare abstract class DynamoDBOperation<T> {
|
|
22
|
+
protected auditMetadata?: Record<string, unknown>;
|
|
23
|
+
protected logger?: DynamoDBOperationOptions['logger'];
|
|
24
|
+
protected errorHandler?: DynamoDBOperationOptions['errorHandler'];
|
|
25
|
+
constructor(options?: DynamoDBOperationOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Attach audit metadata to this operation. Can be chained.
|
|
28
|
+
*/
|
|
29
|
+
audit(config: AuditConfig): this;
|
|
30
|
+
/**
|
|
31
|
+
* Get the audit metadata for this operation.
|
|
32
|
+
*/
|
|
33
|
+
protected getAuditData(): AuditData;
|
|
34
|
+
/**
|
|
35
|
+
* Execute the operation and return a Result
|
|
36
|
+
*/
|
|
37
|
+
abstract execute(): Promise<Result<T, EncryptedDynamoDBError>>;
|
|
38
|
+
/**
|
|
39
|
+
* Make the operation thenable
|
|
40
|
+
*/
|
|
41
|
+
then<TResult1 = Result<T, EncryptedDynamoDBError>, TResult2 = never>(onfulfilled?: ((value: Result<T, EncryptedDynamoDBError>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare class BulkDecryptModelsOperation<T extends Record<string, unknown>> extends DynamoDBOperation<Decrypted<T>[]> {
|
|
45
|
+
private encryptionClient;
|
|
46
|
+
private items;
|
|
47
|
+
private table;
|
|
48
|
+
constructor(encryptionClient: EncryptionClient, items: Record<string, EncryptedValue | unknown>[], table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
49
|
+
execute(): Promise<Result<Decrypted<T>[], EncryptedDynamoDBError>>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
declare class BulkEncryptModelsOperation<T extends Record<string, unknown>> extends DynamoDBOperation<T[]> {
|
|
53
|
+
private encryptionClient;
|
|
54
|
+
private items;
|
|
55
|
+
private table;
|
|
56
|
+
constructor(encryptionClient: EncryptionClient, items: T[], table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
57
|
+
execute(): Promise<Result<T[], EncryptedDynamoDBError>>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare class DecryptModelOperation<T extends Record<string, unknown>> extends DynamoDBOperation<Decrypted<T>> {
|
|
61
|
+
private encryptionClient;
|
|
62
|
+
private item;
|
|
63
|
+
private table;
|
|
64
|
+
constructor(encryptionClient: EncryptionClient, item: Record<string, EncryptedValue | unknown>, table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
65
|
+
execute(): Promise<Result<Decrypted<T>, EncryptedDynamoDBError>>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
declare class EncryptModelOperation<T extends Record<string, unknown>> extends DynamoDBOperation<T> {
|
|
69
|
+
private encryptionClient;
|
|
70
|
+
private item;
|
|
71
|
+
private table;
|
|
72
|
+
constructor(encryptionClient: EncryptionClient, item: T, table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
73
|
+
execute(): Promise<Result<T, EncryptedDynamoDBError>>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface EncryptedDynamoDBConfig {
|
|
77
|
+
encryptionClient: EncryptionClient;
|
|
78
|
+
options?: {
|
|
79
|
+
logger?: {
|
|
80
|
+
error: (message: string, error: Error) => void;
|
|
81
|
+
};
|
|
82
|
+
errorHandler?: (error: EncryptedDynamoDBError) => void;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
interface EncryptedDynamoDBError extends Error {
|
|
86
|
+
code: ProtectErrorCode | 'DYNAMODB_ENCRYPTION_ERROR';
|
|
87
|
+
details?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
interface EncryptedDynamoDBInstance {
|
|
90
|
+
encryptModel<T extends Record<string, unknown>>(item: T, table: ProtectTable<ProtectTableColumn>): EncryptModelOperation<T>;
|
|
91
|
+
bulkEncryptModels<T extends Record<string, unknown>>(items: T[], table: ProtectTable<ProtectTableColumn>): BulkEncryptModelsOperation<T>;
|
|
92
|
+
decryptModel<T extends Record<string, unknown>>(item: Record<string, EncryptedValue | unknown>, table: ProtectTable<ProtectTableColumn>): DecryptModelOperation<T>;
|
|
93
|
+
bulkDecryptModels<T extends Record<string, unknown>>(items: Record<string, EncryptedValue | unknown>[], table: ProtectTable<ProtectTableColumn>): BulkDecryptModelsOperation<T>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Create an encrypted DynamoDB helper bound to an `EncryptionClient`.
|
|
98
|
+
*
|
|
99
|
+
* Returns an object with `encryptModel`, `decryptModel`, `bulkEncryptModels`,
|
|
100
|
+
* and `bulkDecryptModels` methods that transparently encrypt/decrypt DynamoDB
|
|
101
|
+
* items according to the provided table schema.
|
|
102
|
+
*
|
|
103
|
+
* @param config - Configuration containing the `encryptionClient` and optional
|
|
104
|
+
* logging / error-handling callbacks.
|
|
105
|
+
* @returns An {@link EncryptedDynamoDBInstance} with encrypt/decrypt operations.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* import { Encryption } from "@cipherstash/stack"
|
|
110
|
+
* import { encryptedDynamoDB } from "@cipherstash/stack/dynamodb"
|
|
111
|
+
* import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
|
|
112
|
+
*
|
|
113
|
+
* const users = encryptedTable("users", {
|
|
114
|
+
* email: encryptedColumn("email").equality(),
|
|
115
|
+
* })
|
|
116
|
+
*
|
|
117
|
+
* const client = await Encryption({ schemas: [users] })
|
|
118
|
+
* const dynamo = encryptedDynamoDB({ encryptionClient: client })
|
|
119
|
+
*
|
|
120
|
+
* const encrypted = await dynamo.encryptModel({ email: "a@b.com" }, users)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
declare function encryptedDynamoDB(config: EncryptedDynamoDBConfig): EncryptedDynamoDBInstance;
|
|
124
|
+
|
|
125
|
+
export { type EncryptedDynamoDBConfig, type EncryptedDynamoDBError, type EncryptedDynamoDBInstance, encryptedDynamoDB };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { E as EncryptionClient } from '../client-DtGq9dJp.js';
|
|
2
|
+
import { D as Decrypted, i as EncryptedValue, d as ProtectTable, f as ProtectTableColumn } from '../types-public-BCj1L4fi.js';
|
|
3
|
+
import { ProtectErrorCode } from '@cipherstash/protect-ffi';
|
|
4
|
+
import { Result } from '@byteslice/result';
|
|
5
|
+
import '../index-9-Ya3fDK.js';
|
|
6
|
+
import 'zod';
|
|
7
|
+
import 'evlog';
|
|
8
|
+
|
|
9
|
+
type AuditConfig = {
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
type AuditData = {
|
|
13
|
+
metadata?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
type DynamoDBOperationOptions = {
|
|
16
|
+
logger?: {
|
|
17
|
+
error: (message: string, error: Error) => void;
|
|
18
|
+
};
|
|
19
|
+
errorHandler?: (error: EncryptedDynamoDBError) => void;
|
|
20
|
+
};
|
|
21
|
+
declare abstract class DynamoDBOperation<T> {
|
|
22
|
+
protected auditMetadata?: Record<string, unknown>;
|
|
23
|
+
protected logger?: DynamoDBOperationOptions['logger'];
|
|
24
|
+
protected errorHandler?: DynamoDBOperationOptions['errorHandler'];
|
|
25
|
+
constructor(options?: DynamoDBOperationOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Attach audit metadata to this operation. Can be chained.
|
|
28
|
+
*/
|
|
29
|
+
audit(config: AuditConfig): this;
|
|
30
|
+
/**
|
|
31
|
+
* Get the audit metadata for this operation.
|
|
32
|
+
*/
|
|
33
|
+
protected getAuditData(): AuditData;
|
|
34
|
+
/**
|
|
35
|
+
* Execute the operation and return a Result
|
|
36
|
+
*/
|
|
37
|
+
abstract execute(): Promise<Result<T, EncryptedDynamoDBError>>;
|
|
38
|
+
/**
|
|
39
|
+
* Make the operation thenable
|
|
40
|
+
*/
|
|
41
|
+
then<TResult1 = Result<T, EncryptedDynamoDBError>, TResult2 = never>(onfulfilled?: ((value: Result<T, EncryptedDynamoDBError>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare class BulkDecryptModelsOperation<T extends Record<string, unknown>> extends DynamoDBOperation<Decrypted<T>[]> {
|
|
45
|
+
private encryptionClient;
|
|
46
|
+
private items;
|
|
47
|
+
private table;
|
|
48
|
+
constructor(encryptionClient: EncryptionClient, items: Record<string, EncryptedValue | unknown>[], table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
49
|
+
execute(): Promise<Result<Decrypted<T>[], EncryptedDynamoDBError>>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
declare class BulkEncryptModelsOperation<T extends Record<string, unknown>> extends DynamoDBOperation<T[]> {
|
|
53
|
+
private encryptionClient;
|
|
54
|
+
private items;
|
|
55
|
+
private table;
|
|
56
|
+
constructor(encryptionClient: EncryptionClient, items: T[], table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
57
|
+
execute(): Promise<Result<T[], EncryptedDynamoDBError>>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare class DecryptModelOperation<T extends Record<string, unknown>> extends DynamoDBOperation<Decrypted<T>> {
|
|
61
|
+
private encryptionClient;
|
|
62
|
+
private item;
|
|
63
|
+
private table;
|
|
64
|
+
constructor(encryptionClient: EncryptionClient, item: Record<string, EncryptedValue | unknown>, table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
65
|
+
execute(): Promise<Result<Decrypted<T>, EncryptedDynamoDBError>>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
declare class EncryptModelOperation<T extends Record<string, unknown>> extends DynamoDBOperation<T> {
|
|
69
|
+
private encryptionClient;
|
|
70
|
+
private item;
|
|
71
|
+
private table;
|
|
72
|
+
constructor(encryptionClient: EncryptionClient, item: T, table: ProtectTable<ProtectTableColumn>, options?: DynamoDBOperationOptions);
|
|
73
|
+
execute(): Promise<Result<T, EncryptedDynamoDBError>>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface EncryptedDynamoDBConfig {
|
|
77
|
+
encryptionClient: EncryptionClient;
|
|
78
|
+
options?: {
|
|
79
|
+
logger?: {
|
|
80
|
+
error: (message: string, error: Error) => void;
|
|
81
|
+
};
|
|
82
|
+
errorHandler?: (error: EncryptedDynamoDBError) => void;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
interface EncryptedDynamoDBError extends Error {
|
|
86
|
+
code: ProtectErrorCode | 'DYNAMODB_ENCRYPTION_ERROR';
|
|
87
|
+
details?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
interface EncryptedDynamoDBInstance {
|
|
90
|
+
encryptModel<T extends Record<string, unknown>>(item: T, table: ProtectTable<ProtectTableColumn>): EncryptModelOperation<T>;
|
|
91
|
+
bulkEncryptModels<T extends Record<string, unknown>>(items: T[], table: ProtectTable<ProtectTableColumn>): BulkEncryptModelsOperation<T>;
|
|
92
|
+
decryptModel<T extends Record<string, unknown>>(item: Record<string, EncryptedValue | unknown>, table: ProtectTable<ProtectTableColumn>): DecryptModelOperation<T>;
|
|
93
|
+
bulkDecryptModels<T extends Record<string, unknown>>(items: Record<string, EncryptedValue | unknown>[], table: ProtectTable<ProtectTableColumn>): BulkDecryptModelsOperation<T>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Create an encrypted DynamoDB helper bound to an `EncryptionClient`.
|
|
98
|
+
*
|
|
99
|
+
* Returns an object with `encryptModel`, `decryptModel`, `bulkEncryptModels`,
|
|
100
|
+
* and `bulkDecryptModels` methods that transparently encrypt/decrypt DynamoDB
|
|
101
|
+
* items according to the provided table schema.
|
|
102
|
+
*
|
|
103
|
+
* @param config - Configuration containing the `encryptionClient` and optional
|
|
104
|
+
* logging / error-handling callbacks.
|
|
105
|
+
* @returns An {@link EncryptedDynamoDBInstance} with encrypt/decrypt operations.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* import { Encryption } from "@cipherstash/stack"
|
|
110
|
+
* import { encryptedDynamoDB } from "@cipherstash/stack/dynamodb"
|
|
111
|
+
* import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"
|
|
112
|
+
*
|
|
113
|
+
* const users = encryptedTable("users", {
|
|
114
|
+
* email: encryptedColumn("email").equality(),
|
|
115
|
+
* })
|
|
116
|
+
*
|
|
117
|
+
* const client = await Encryption({ schemas: [users] })
|
|
118
|
+
* const dynamo = encryptedDynamoDB({ encryptionClient: client })
|
|
119
|
+
*
|
|
120
|
+
* const encrypted = await dynamo.encryptModel({ email: "a@b.com" }, users)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
declare function encryptedDynamoDB(config: EncryptedDynamoDBConfig): EncryptedDynamoDBInstance;
|
|
124
|
+
|
|
125
|
+
export { type EncryptedDynamoDBConfig, type EncryptedDynamoDBError, type EncryptedDynamoDBInstance, encryptedDynamoDB };
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// src/dynamodb/operations/bulk-decrypt-models.ts
|
|
2
|
+
import { withResult } from "@byteslice/result";
|
|
3
|
+
|
|
4
|
+
// src/dynamodb/helpers.ts
|
|
5
|
+
import { ProtectError as FfiProtectError } from "@cipherstash/protect-ffi";
|
|
6
|
+
var ciphertextAttrSuffix = "__source";
|
|
7
|
+
var searchTermAttrSuffix = "__hmac";
|
|
8
|
+
var EncryptedDynamoDBErrorImpl = class extends Error {
|
|
9
|
+
constructor(message, code, details) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.details = details;
|
|
13
|
+
this.name = "EncryptedDynamoDBError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function handleError(error, context, options) {
|
|
17
|
+
const errorObj = error;
|
|
18
|
+
const errorCode = error instanceof FfiProtectError ? error.code : errorObj && typeof errorObj === "object" && "code" in errorObj && typeof errorObj.code === "string" ? errorObj.code : "DYNAMODB_ENCRYPTION_ERROR";
|
|
19
|
+
const errorMessage = error instanceof Error ? error.message : errorObj && typeof errorObj.message === "string" ? errorObj.message : String(error);
|
|
20
|
+
const dynamoError = new EncryptedDynamoDBErrorImpl(errorMessage, errorCode, {
|
|
21
|
+
context
|
|
22
|
+
});
|
|
23
|
+
if (options?.errorHandler) {
|
|
24
|
+
options.errorHandler(dynamoError);
|
|
25
|
+
}
|
|
26
|
+
if (options?.logger) {
|
|
27
|
+
options.logger.error(`Error in ${context}`, dynamoError);
|
|
28
|
+
}
|
|
29
|
+
return dynamoError;
|
|
30
|
+
}
|
|
31
|
+
function deepClone(obj) {
|
|
32
|
+
if (obj === null || typeof obj !== "object") {
|
|
33
|
+
return obj;
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(obj)) {
|
|
36
|
+
return obj.map((item) => deepClone(item));
|
|
37
|
+
}
|
|
38
|
+
return Object.entries(obj).reduce(
|
|
39
|
+
(acc, [key, value]) => ({
|
|
40
|
+
// biome-ignore lint/performance/noAccumulatingSpread: TODO later
|
|
41
|
+
...acc,
|
|
42
|
+
[key]: deepClone(value)
|
|
43
|
+
}),
|
|
44
|
+
{}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function toEncryptedDynamoItem(encrypted, encryptedAttrs) {
|
|
48
|
+
function processValue(attrName, attrValue, isNested) {
|
|
49
|
+
if (attrValue === null || attrValue === void 0) {
|
|
50
|
+
return { [attrName]: attrValue };
|
|
51
|
+
}
|
|
52
|
+
if (encryptedAttrs.includes(attrName) || isNested && typeof attrValue === "object" && "c" in attrValue) {
|
|
53
|
+
const encryptPayload = attrValue;
|
|
54
|
+
if (encryptPayload?.c) {
|
|
55
|
+
const result = {};
|
|
56
|
+
if (encryptPayload.hm) {
|
|
57
|
+
result[`${attrName}${searchTermAttrSuffix}`] = encryptPayload.hm;
|
|
58
|
+
}
|
|
59
|
+
result[`${attrName}${ciphertextAttrSuffix}`] = encryptPayload.c;
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
if (encryptPayload?.sv) {
|
|
63
|
+
const result = {};
|
|
64
|
+
result[`${attrName}${ciphertextAttrSuffix}`] = encryptPayload.sv;
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (typeof attrValue === "object" && !Array.isArray(attrValue)) {
|
|
69
|
+
const nestedResult = Object.entries(
|
|
70
|
+
attrValue
|
|
71
|
+
).reduce(
|
|
72
|
+
(acc, [key, val]) => {
|
|
73
|
+
const processed = processValue(key, val, true);
|
|
74
|
+
return Object.assign({}, acc, processed);
|
|
75
|
+
},
|
|
76
|
+
{}
|
|
77
|
+
);
|
|
78
|
+
return { [attrName]: nestedResult };
|
|
79
|
+
}
|
|
80
|
+
return { [attrName]: attrValue };
|
|
81
|
+
}
|
|
82
|
+
return Object.entries(encrypted).reduce(
|
|
83
|
+
(putItem, [attrName, attrValue]) => {
|
|
84
|
+
const processed = processValue(attrName, attrValue, false);
|
|
85
|
+
return Object.assign({}, putItem, processed);
|
|
86
|
+
},
|
|
87
|
+
{}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function toItemWithEqlPayloads(decrypted, encryptionSchema) {
|
|
91
|
+
function processValue(attrName, attrValue, isNested) {
|
|
92
|
+
if (attrValue === null || attrValue === void 0) {
|
|
93
|
+
return { [attrName]: attrValue };
|
|
94
|
+
}
|
|
95
|
+
if (attrName.endsWith(searchTermAttrSuffix)) {
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
const encryptConfig = encryptionSchema.build();
|
|
99
|
+
const encryptedAttrs = Object.keys(encryptConfig.columns);
|
|
100
|
+
const columnName = attrName.slice(0, -ciphertextAttrSuffix.length);
|
|
101
|
+
if (attrName.endsWith(ciphertextAttrSuffix) && (encryptedAttrs.includes(columnName) || isNested)) {
|
|
102
|
+
const i = { c: columnName, t: encryptConfig.tableName };
|
|
103
|
+
const v = 2;
|
|
104
|
+
if (!isNested && encryptConfig.columns[columnName].cast_as === "json" && encryptConfig.columns[columnName].indexes.ste_vec) {
|
|
105
|
+
return {
|
|
106
|
+
[columnName]: {
|
|
107
|
+
i,
|
|
108
|
+
v,
|
|
109
|
+
k: "sv",
|
|
110
|
+
sv: attrValue
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
[columnName]: {
|
|
116
|
+
i,
|
|
117
|
+
v,
|
|
118
|
+
k: "ct",
|
|
119
|
+
c: attrValue
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (typeof attrValue === "object" && !Array.isArray(attrValue)) {
|
|
124
|
+
const nestedResult = Object.entries(
|
|
125
|
+
attrValue
|
|
126
|
+
).reduce(
|
|
127
|
+
(acc, [key, val]) => {
|
|
128
|
+
const processed = processValue(key, val, true);
|
|
129
|
+
return Object.assign({}, acc, processed);
|
|
130
|
+
},
|
|
131
|
+
{}
|
|
132
|
+
);
|
|
133
|
+
return { [attrName]: nestedResult };
|
|
134
|
+
}
|
|
135
|
+
return { [attrName]: attrValue };
|
|
136
|
+
}
|
|
137
|
+
return Object.entries(decrypted).reduce(
|
|
138
|
+
(formattedItem, [attrName, attrValue]) => {
|
|
139
|
+
const processed = processValue(attrName, attrValue, false);
|
|
140
|
+
return Object.assign({}, formattedItem, processed);
|
|
141
|
+
},
|
|
142
|
+
{}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/dynamodb/operations/base-operation.ts
|
|
147
|
+
var DynamoDBOperation = class {
|
|
148
|
+
auditMetadata;
|
|
149
|
+
logger;
|
|
150
|
+
errorHandler;
|
|
151
|
+
constructor(options) {
|
|
152
|
+
this.logger = options?.logger;
|
|
153
|
+
this.errorHandler = options?.errorHandler;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Attach audit metadata to this operation. Can be chained.
|
|
157
|
+
*/
|
|
158
|
+
audit(config) {
|
|
159
|
+
this.auditMetadata = config.metadata;
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get the audit metadata for this operation.
|
|
164
|
+
*/
|
|
165
|
+
getAuditData() {
|
|
166
|
+
return {
|
|
167
|
+
metadata: this.auditMetadata
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Make the operation thenable
|
|
172
|
+
*/
|
|
173
|
+
then(onfulfilled, onrejected) {
|
|
174
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/dynamodb/operations/bulk-decrypt-models.ts
|
|
179
|
+
var BulkDecryptModelsOperation = class extends DynamoDBOperation {
|
|
180
|
+
encryptionClient;
|
|
181
|
+
items;
|
|
182
|
+
table;
|
|
183
|
+
constructor(encryptionClient, items, table, options) {
|
|
184
|
+
super(options);
|
|
185
|
+
this.encryptionClient = encryptionClient;
|
|
186
|
+
this.items = items;
|
|
187
|
+
this.table = table;
|
|
188
|
+
}
|
|
189
|
+
async execute() {
|
|
190
|
+
return await withResult(
|
|
191
|
+
async () => {
|
|
192
|
+
const itemsWithEqlPayloads = this.items.map(
|
|
193
|
+
(item) => toItemWithEqlPayloads(item, this.table)
|
|
194
|
+
);
|
|
195
|
+
const decryptResult = await this.encryptionClient.bulkDecryptModels(itemsWithEqlPayloads).audit(this.getAuditData());
|
|
196
|
+
if (decryptResult.failure) {
|
|
197
|
+
const error = new Error(decryptResult.failure.message);
|
|
198
|
+
error.code = decryptResult.failure.code;
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
return decryptResult.data;
|
|
202
|
+
},
|
|
203
|
+
(error) => handleError(error, "bulkDecryptModels", {
|
|
204
|
+
logger: this.logger,
|
|
205
|
+
errorHandler: this.errorHandler
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/dynamodb/operations/bulk-encrypt-models.ts
|
|
212
|
+
import { withResult as withResult2 } from "@byteslice/result";
|
|
213
|
+
var BulkEncryptModelsOperation = class extends DynamoDBOperation {
|
|
214
|
+
encryptionClient;
|
|
215
|
+
items;
|
|
216
|
+
table;
|
|
217
|
+
constructor(encryptionClient, items, table, options) {
|
|
218
|
+
super(options);
|
|
219
|
+
this.encryptionClient = encryptionClient;
|
|
220
|
+
this.items = items;
|
|
221
|
+
this.table = table;
|
|
222
|
+
}
|
|
223
|
+
async execute() {
|
|
224
|
+
return await withResult2(
|
|
225
|
+
async () => {
|
|
226
|
+
const encryptResult = await this.encryptionClient.bulkEncryptModels(
|
|
227
|
+
this.items.map((item) => deepClone(item)),
|
|
228
|
+
this.table
|
|
229
|
+
).audit(this.getAuditData());
|
|
230
|
+
if (encryptResult.failure) {
|
|
231
|
+
const error = new Error(encryptResult.failure.message);
|
|
232
|
+
error.code = encryptResult.failure.code;
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
const data = encryptResult.data.map((item) => deepClone(item));
|
|
236
|
+
const encryptedAttrs = Object.keys(this.table.build().columns);
|
|
237
|
+
return data.map(
|
|
238
|
+
(encrypted) => toEncryptedDynamoItem(encrypted, encryptedAttrs)
|
|
239
|
+
);
|
|
240
|
+
},
|
|
241
|
+
(error) => handleError(error, "bulkEncryptModels", {
|
|
242
|
+
logger: this.logger,
|
|
243
|
+
errorHandler: this.errorHandler
|
|
244
|
+
})
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/dynamodb/operations/decrypt-model.ts
|
|
250
|
+
import { withResult as withResult3 } from "@byteslice/result";
|
|
251
|
+
var DecryptModelOperation = class extends DynamoDBOperation {
|
|
252
|
+
encryptionClient;
|
|
253
|
+
item;
|
|
254
|
+
table;
|
|
255
|
+
constructor(encryptionClient, item, table, options) {
|
|
256
|
+
super(options);
|
|
257
|
+
this.encryptionClient = encryptionClient;
|
|
258
|
+
this.item = item;
|
|
259
|
+
this.table = table;
|
|
260
|
+
}
|
|
261
|
+
async execute() {
|
|
262
|
+
return await withResult3(
|
|
263
|
+
async () => {
|
|
264
|
+
const withEqlPayloads = toItemWithEqlPayloads(this.item, this.table);
|
|
265
|
+
const decryptResult = await this.encryptionClient.decryptModel(withEqlPayloads).audit(this.getAuditData());
|
|
266
|
+
if (decryptResult.failure) {
|
|
267
|
+
const error = new Error(decryptResult.failure.message);
|
|
268
|
+
error.code = decryptResult.failure.code;
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
return decryptResult.data;
|
|
272
|
+
},
|
|
273
|
+
(error) => handleError(error, "decryptModel", {
|
|
274
|
+
logger: this.logger,
|
|
275
|
+
errorHandler: this.errorHandler
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// src/dynamodb/operations/encrypt-model.ts
|
|
282
|
+
import { withResult as withResult4 } from "@byteslice/result";
|
|
283
|
+
var EncryptModelOperation = class extends DynamoDBOperation {
|
|
284
|
+
encryptionClient;
|
|
285
|
+
item;
|
|
286
|
+
table;
|
|
287
|
+
constructor(encryptionClient, item, table, options) {
|
|
288
|
+
super(options);
|
|
289
|
+
this.encryptionClient = encryptionClient;
|
|
290
|
+
this.item = item;
|
|
291
|
+
this.table = table;
|
|
292
|
+
}
|
|
293
|
+
async execute() {
|
|
294
|
+
return await withResult4(
|
|
295
|
+
async () => {
|
|
296
|
+
const encryptResult = await this.encryptionClient.encryptModel(deepClone(this.item), this.table).audit(this.getAuditData());
|
|
297
|
+
if (encryptResult.failure) {
|
|
298
|
+
const error = new Error(encryptResult.failure.message);
|
|
299
|
+
error.code = encryptResult.failure.code;
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
const data = deepClone(encryptResult.data);
|
|
303
|
+
const encryptedAttrs = Object.keys(this.table.build().columns);
|
|
304
|
+
return toEncryptedDynamoItem(data, encryptedAttrs);
|
|
305
|
+
},
|
|
306
|
+
(error) => handleError(error, "encryptModel", {
|
|
307
|
+
logger: this.logger,
|
|
308
|
+
errorHandler: this.errorHandler
|
|
309
|
+
})
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/dynamodb/index.ts
|
|
315
|
+
function encryptedDynamoDB(config) {
|
|
316
|
+
const { encryptionClient, options } = config;
|
|
317
|
+
return {
|
|
318
|
+
encryptModel(item, table) {
|
|
319
|
+
return new EncryptModelOperation(
|
|
320
|
+
encryptionClient,
|
|
321
|
+
item,
|
|
322
|
+
table,
|
|
323
|
+
options
|
|
324
|
+
);
|
|
325
|
+
},
|
|
326
|
+
bulkEncryptModels(items, table) {
|
|
327
|
+
return new BulkEncryptModelsOperation(
|
|
328
|
+
encryptionClient,
|
|
329
|
+
items,
|
|
330
|
+
table,
|
|
331
|
+
options
|
|
332
|
+
);
|
|
333
|
+
},
|
|
334
|
+
decryptModel(item, table) {
|
|
335
|
+
return new DecryptModelOperation(
|
|
336
|
+
encryptionClient,
|
|
337
|
+
item,
|
|
338
|
+
table,
|
|
339
|
+
options
|
|
340
|
+
);
|
|
341
|
+
},
|
|
342
|
+
bulkDecryptModels(items, table) {
|
|
343
|
+
return new BulkDecryptModelsOperation(
|
|
344
|
+
encryptionClient,
|
|
345
|
+
items,
|
|
346
|
+
table,
|
|
347
|
+
options
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
export {
|
|
353
|
+
encryptedDynamoDB
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=index.js.map
|