From 19331ac377e86771722c5cec7e0b80d44f64e760 Mon Sep 17 00:00:00 2001 From: Dan Draper Date: Wed, 8 Jul 2026 18:16:44 +1000 Subject: [PATCH] =?UTF-8?q?chore(stack):=20upgrade=20@byteslice/result=200?= =?UTF-8?q?.2=20=E2=86=92=200.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.5's `FailureOption` no longer accepts a bare `{ type }` shape — a failure must be an `Error` or carry an `error: Error`. This aligns stack with `@cipherstash/auth` 0.41 (which already ships 0.5's Result) and unblocks the tracked byteslice migration. - `EncryptionError` gains a required `error: Error` holding the originating error; `type` / `message` / `code` are unchanged, so readers of `result.failure.*` are unaffected. - New `toEncryptionError(type, error, code?)` factory coerces any caught value to a real `Error` (never an unchecked `as Error`) and derives the message; all 27 hand-built failure literals across encryption/* + identity now route through it. Verified: `tsc` clean, `tsup` build clean, biome clean. Offline suites (validation, wasm-inline strategy, cjs-require) pass; remaining suite failures are the pre-existing live-integration tests that need local CipherStash creds. --- .changeset/byteslice-result-0-5.md | 5 +++ packages/stack/package.json | 2 +- .../src/encryption/helpers/validation.ts | 32 +++++++++++-------- packages/stack/src/encryption/index.ts | 12 ++++--- .../operations/batch-encrypt-query.ts | 26 ++++++++------- .../operations/bulk-decrypt-models.ts | 26 ++++++++------- .../src/encryption/operations/bulk-decrypt.ts | 26 ++++++++------- .../operations/bulk-encrypt-models.ts | 26 ++++++++------- .../src/encryption/operations/bulk-encrypt.ts | 26 ++++++++------- .../encryption/operations/decrypt-model.ts | 26 ++++++++------- .../src/encryption/operations/decrypt.ts | 26 ++++++++------- .../encryption/operations/encrypt-model.ts | 26 ++++++++------- .../encryption/operations/encrypt-query.ts | 26 ++++++++------- .../src/encryption/operations/encrypt.ts | 26 ++++++++------- packages/stack/src/errors/index.ts | 25 +++++++++++++++ packages/stack/src/identity/index.ts | 21 +++++------- pnpm-lock.yaml | 9 ++++-- 17 files changed, 222 insertions(+), 144 deletions(-) create mode 100644 .changeset/byteslice-result-0-5.md diff --git a/.changeset/byteslice-result-0-5.md b/.changeset/byteslice-result-0-5.md new file mode 100644 index 00000000..7fbdcf88 --- /dev/null +++ b/.changeset/byteslice-result-0-5.md @@ -0,0 +1,5 @@ +--- +'@cipherstash/stack': minor +--- + +Upgrade `@byteslice/result` to 0.5.0. Its `FailureOption` no longer accepts a bare `{ type }` shape — a failure must be an `Error` or carry an `error: Error`. `EncryptionError` now includes a required `error: Error` holding the originating error, and all failures are built through the new `toEncryptionError(type, error, code?)` factory (which coerces any caught value to a real `Error`). The existing `type` / `message` / `code` fields are unchanged, so code that reads `result.failure.type` / `.message` / `.code` keeps working. diff --git a/packages/stack/package.json b/packages/stack/package.json index 5efb71b2..20898cb6 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -242,7 +242,7 @@ "access": "public" }, "dependencies": { - "@byteslice/result": "0.2.0", + "@byteslice/result": "0.5.0", "@cipherstash/auth": "catalog:repo", "@cipherstash/protect-ffi": "0.28.0", "evlog": "1.11.0", diff --git a/packages/stack/src/encryption/helpers/validation.ts b/packages/stack/src/encryption/helpers/validation.ts index ab411040..6a281f46 100644 --- a/packages/stack/src/encryption/helpers/validation.ts +++ b/packages/stack/src/encryption/helpers/validation.ts @@ -1,5 +1,9 @@ import type { Result } from '@byteslice/result' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import type { FfiIndexTypeName } from '@/types' /** @@ -16,18 +20,18 @@ export function validateNumericValue( ): Result | undefined { if (typeof value === 'number' && Number.isNaN(value)) { return { - failure: { - type: EncryptionErrorTypes.EncryptionError, - message: '[encryption]: Cannot encrypt NaN value', - }, + failure: toEncryptionError( + EncryptionErrorTypes.EncryptionError, + new Error('[encryption]: Cannot encrypt NaN value'), + ), } } if (typeof value === 'number' && !Number.isFinite(value)) { return { - failure: { - type: EncryptionErrorTypes.EncryptionError, - message: '[encryption]: Cannot encrypt Infinity value', - }, + failure: toEncryptionError( + EncryptionErrorTypes.EncryptionError, + new Error('[encryption]: Cannot encrypt Infinity value'), + ), } } return undefined @@ -64,10 +68,12 @@ export function validateValueIndexCompatibility( ): Result | undefined { if (typeof value === 'number' && indexType === 'match') { return { - failure: { - type: EncryptionErrorTypes.EncryptionError, - message: `[encryption]: Cannot use 'match' index with numeric value on column "${columnName}". The 'freeTextSearch' index only supports string values. Configure the column with 'orderAndRange()' or 'equality()' for numeric queries.`, - }, + failure: toEncryptionError( + EncryptionErrorTypes.EncryptionError, + new Error( + `[encryption]: Cannot use 'match' index with numeric value on column "${columnName}". The 'freeTextSearch' index only supports string values. Configure the column with 'orderAndRange()' or 'equality()' for numeric queries.`, + ), + ), } } return undefined diff --git a/packages/stack/src/encryption/index.ts b/packages/stack/src/encryption/index.ts index d07bf8d9..e53fba9b 100644 --- a/packages/stack/src/encryption/index.ts +++ b/packages/stack/src/encryption/index.ts @@ -1,7 +1,11 @@ import { type Result, withResult } from '@byteslice/result' import { newClient } from '@cipherstash/protect-ffi' import { validate as uuidValidate } from 'uuid' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' // `LockContext` is imported type-only so the TSDoc {@link} references in the // comments below resolve; it is erased at compile time. import type { LockContext } from '@/identity' @@ -172,10 +176,8 @@ export class EncryptionClient { logger.debug('Successfully initialized the Encryption client.') return this }, - (error: unknown) => ({ - type: EncryptionErrorTypes.ClientInitError, - message: (error as Error).message, - }), + (error: unknown) => + toEncryptionError(EncryptionErrorTypes.ClientInitError, error), ) } diff --git a/packages/stack/src/encryption/operations/batch-encrypt-query.ts b/packages/stack/src/encryption/operations/batch-encrypt-query.ts index ca5cfb3b..a7f42c76 100644 --- a/packages/stack/src/encryption/operations/batch-encrypt-query.ts +++ b/packages/stack/src/encryption/operations/batch-encrypt-query.ts @@ -11,7 +11,11 @@ import { } from '@cipherstash/protect-ffi' import { formatEncryptedResult } from '@/encryption/helpers' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type Context, type LockContextInput, @@ -162,11 +166,11 @@ export class BatchEncryptQueryOperation extends EncryptionOperation< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -230,11 +234,11 @@ export class BatchEncryptQueryOperationWithLockContext extends EncryptionOperati }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/bulk-decrypt-models.ts b/packages/stack/src/encryption/operations/bulk-decrypt-models.ts index 4b38615a..bdbfd586 100644 --- a/packages/stack/src/encryption/operations/bulk-decrypt-models.ts +++ b/packages/stack/src/encryption/operations/bulk-decrypt-models.ts @@ -1,6 +1,10 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { Client, Decrypted } from '@/types' import { createRequestLogger } from '@/utils/logger' @@ -49,11 +53,11 @@ export class BulkDecryptModelsOperation< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -119,11 +123,11 @@ export class BulkDecryptModelsOperationWithLockContext< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/bulk-decrypt.ts b/packages/stack/src/encryption/operations/bulk-decrypt.ts index 0be8c86a..d9310ea7 100644 --- a/packages/stack/src/encryption/operations/bulk-decrypt.ts +++ b/packages/stack/src/encryption/operations/bulk-decrypt.ts @@ -5,7 +5,11 @@ import { decryptBulkFallible, } from '@cipherstash/protect-ffi' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type Context, type LockContextInput, @@ -104,11 +108,11 @@ export class BulkDecryptOperation extends EncryptionOperation }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -177,11 +181,11 @@ export class BulkDecryptOperationWithLockContext extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/bulk-encrypt-models.ts b/packages/stack/src/encryption/operations/bulk-encrypt-models.ts index 10c22633..ee0c4a90 100644 --- a/packages/stack/src/encryption/operations/bulk-encrypt-models.ts +++ b/packages/stack/src/encryption/operations/bulk-encrypt-models.ts @@ -1,6 +1,10 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { BuildableTable, Client } from '@/types' import { createRequestLogger } from '@/utils/logger' @@ -61,11 +65,11 @@ export class BulkEncryptModelsOperation< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -135,11 +139,11 @@ export class BulkEncryptModelsOperationWithLockContext< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/bulk-encrypt.ts b/packages/stack/src/encryption/operations/bulk-encrypt.ts index 6e3ec802..9f8f649e 100644 --- a/packages/stack/src/encryption/operations/bulk-encrypt.ts +++ b/packages/stack/src/encryption/operations/bulk-encrypt.ts @@ -1,7 +1,11 @@ import { type Result, withResult } from '@byteslice/result' import { encryptBulk, type JsPlaintext } from '@cipherstash/protect-ffi' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type Context, type LockContextInput, @@ -124,11 +128,11 @@ export class BulkEncryptOperation extends EncryptionOperation }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -209,11 +213,11 @@ export class BulkEncryptOperationWithLockContext extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/decrypt-model.ts b/packages/stack/src/encryption/operations/decrypt-model.ts index 89c461e2..7ab3f83f 100644 --- a/packages/stack/src/encryption/operations/decrypt-model.ts +++ b/packages/stack/src/encryption/operations/decrypt-model.ts @@ -1,6 +1,10 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { Client, Decrypted } from '@/types' import { createRequestLogger } from '@/utils/logger' @@ -48,11 +52,11 @@ export class DecryptModelOperation< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -117,11 +121,11 @@ export class DecryptModelOperationWithLockContext< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/decrypt.ts b/packages/stack/src/encryption/operations/decrypt.ts index ee3765b1..982f7348 100644 --- a/packages/stack/src/encryption/operations/decrypt.ts +++ b/packages/stack/src/encryption/operations/decrypt.ts @@ -4,7 +4,11 @@ import { type JsPlaintext, } from '@cipherstash/protect-ffi' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { Client, Encrypted } from '@/types' import { createRequestLogger } from '@/utils/logger' @@ -62,11 +66,11 @@ export class DecryptOperation extends EncryptionOperation { }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -131,11 +135,11 @@ export class DecryptOperationWithLockContext extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.DecryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.DecryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/encrypt-model.ts b/packages/stack/src/encryption/operations/encrypt-model.ts index 0ac42f08..782b1482 100644 --- a/packages/stack/src/encryption/operations/encrypt-model.ts +++ b/packages/stack/src/encryption/operations/encrypt-model.ts @@ -1,6 +1,10 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { BuildableTable, Client } from '@/types' import { createRequestLogger } from '@/utils/logger' @@ -60,11 +64,11 @@ export class EncryptModelOperation< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -133,11 +137,11 @@ export class EncryptModelOperationWithLockContext< }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/encrypt-query.ts b/packages/stack/src/encryption/operations/encrypt-query.ts index 9369b91d..e3b46e06 100644 --- a/packages/stack/src/encryption/operations/encrypt-query.ts +++ b/packages/stack/src/encryption/operations/encrypt-query.ts @@ -5,7 +5,11 @@ import { } from '@cipherstash/protect-ffi' import { formatEncryptedResult } from '@/encryption/helpers' import { getErrorCode } from '@/encryption/helpers/error-code' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { Client, @@ -103,11 +107,11 @@ export class EncryptQueryOperation extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -194,11 +198,11 @@ export class EncryptQueryOperationWithLockContext extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/encryption/operations/encrypt.ts b/packages/stack/src/encryption/operations/encrypt.ts index de380613..9a88bd3c 100644 --- a/packages/stack/src/encryption/operations/encrypt.ts +++ b/packages/stack/src/encryption/operations/encrypt.ts @@ -5,7 +5,11 @@ import { } from '@cipherstash/protect-ffi' import { getErrorCode } from '@/encryption/helpers/error-code' import { assertValidNumericValue } from '@/encryption/helpers/validation' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { BuildableColumn, @@ -88,11 +92,11 @@ export class EncryptOperation extends EncryptionOperation { }, (error: unknown) => { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() @@ -164,11 +168,11 @@ export class EncryptOperationWithLockContext extends EncryptionOperation { log.set({ errorCode: getErrorCode(error) ?? 'unknown' }) - return { - type: EncryptionErrorTypes.EncryptionError, - message: (error as Error).message, - code: getErrorCode(error), - } + return toEncryptionError( + EncryptionErrorTypes.EncryptionError, + error, + getErrorCode(error), + ) }, ) log.emit() diff --git a/packages/stack/src/errors/index.ts b/packages/stack/src/errors/index.ts index c3bd280b..dc2e2f26 100644 --- a/packages/stack/src/errors/index.ts +++ b/packages/stack/src/errors/index.ts @@ -34,6 +34,11 @@ export interface EncryptionError { type: (typeof EncryptionErrorTypes)[keyof typeof EncryptionErrorTypes] message: string code?: ProtectErrorCode + // `@byteslice/result` 0.5 requires a failure to be an `Error` or to carry an + // `error: Error`. Hold the originating error here so the structured + // `type`/`message`/`code` fields stay available to callers that narrow on + // them. Build via {@link toEncryptionError} so this is always a real `Error`. + error: Error } // --------------------------------------------------------------------------- @@ -115,3 +120,23 @@ export function getErrorMessage(error: unknown): string { if (typeof error === 'string') return error return String(error) } + +/** + * Build an {@link EncryptionError} from a caught value. + * + * `@byteslice/result` 0.5 requires a failure to be an `Error` or to carry an + * `error: Error`, so this coerces an arbitrary caught value to a real `Error` + * (never a lie) and derives `message` from it, while preserving the structured + * `type` and optional `code` fields callers narrow on. Pass a `new Error(...)` + * for failures that have no underlying caught error (e.g. validation). + */ +export function toEncryptionError( + type: EncryptionError['type'], + error: unknown, + code?: ProtectErrorCode, +): EncryptionError { + const err = error instanceof Error ? error : new Error(getErrorMessage(error)) + return code === undefined + ? { type, message: err.message, error: err } + : { type, message: err.message, code, error: err } +} diff --git a/packages/stack/src/identity/index.ts b/packages/stack/src/identity/index.ts index 97437658..e4307e2b 100644 --- a/packages/stack/src/identity/index.ts +++ b/packages/stack/src/identity/index.ts @@ -1,5 +1,9 @@ import { type Result, withResult } from '@byteslice/result' -import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import { + type EncryptionError, + EncryptionErrorTypes, + toEncryptionError, +} from '@/errors' import { loadWorkSpaceId } from '@/utils/config' import { logger } from '@/utils/logger' @@ -147,10 +151,7 @@ export class LockContext { oidcToken: jwtToken, }), }), - (error) => ({ - type: EncryptionErrorTypes.CtsTokenError, - message: error.message, - }), + (error) => toEncryptionError(EncryptionErrorTypes.CtsTokenError, error), ) if (ctsFetchResult.failure) { @@ -170,10 +171,7 @@ export class LockContext { this.ctsToken = ctsToken return this }, - (error) => ({ - type: EncryptionErrorTypes.CtsTokenError, - message: error.message, - }), + (error) => toEncryptionError(EncryptionErrorTypes.CtsTokenError, error), ) return identifiedLockContext @@ -198,10 +196,7 @@ export class LockContext { // than carrying an explicit `undefined`. ...(this.ctsToken ? { ctsToken: this.ctsToken } : {}), }), - (error) => ({ - type: EncryptionErrorTypes.CtsTokenError, - message: error.message, - }), + (error) => toEncryptionError(EncryptionErrorTypes.CtsTokenError, error), ) } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3023ed14..e9131b07 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -572,8 +572,8 @@ importers: packages/stack: dependencies: '@byteslice/result': - specifier: 0.2.0 - version: 0.2.0 + specifier: 0.5.0 + version: 0.5.0 '@cipherstash/auth': specifier: catalog:repo version: 0.41.0(@cipherstash/auth-darwin-arm64@0.41.0)(@cipherstash/auth-darwin-x64@0.41.0)(@cipherstash/auth-linux-arm64-gnu@0.41.0)(@cipherstash/auth-linux-x64-gnu@0.41.0)(@cipherstash/auth-linux-x64-musl@0.41.0)(@cipherstash/auth-win32-x64-msvc@0.41.0) @@ -858,6 +858,9 @@ packages: '@byteslice/result@0.3.0': resolution: {integrity: sha512-nIVjzVJ5LEUsj5jZ196OQ+XFYDPw74JVmHrsKs0g/iX1c8llydLWKbseMKmAtcEnpRj8hdsEue5H/naz7wdC4A==} + '@byteslice/result@0.5.0': + resolution: {integrity: sha512-A0N1+T/VOcFKWkDPkHtge4WKP2Swd/wmpfU8KF0eXvUqsv3YSKZ7r/752RrTnGu9SB+CAhoBHh0v89g3j3O4IQ==} + '@changesets/apply-release-plan@7.1.1': resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} @@ -4142,6 +4145,8 @@ snapshots: '@byteslice/result@0.3.0': {} + '@byteslice/result@0.5.0': {} + '@changesets/apply-release-plan@7.1.1': dependencies: '@changesets/config': 3.1.4