180 lines · 5.9 KB · TypeScript
RawDownload
import * as Predicate from "effect/Predicate";import * as Schema from "effect/Schema";import * as SchemaIssue from "effect/SchemaIssue"; function summarizeSchemaIssue(issue: SchemaIssue.Issue): string {  switch (issue._tag) {    case "Filter":    case "Encoding":    case "Pointer":      return `${issue._tag}(${summarizeSchemaIssue(issue.issue)})`;    case "Composite":    case "AnyOf":      return `${issue._tag}(${issue.issues.map(summarizeSchemaIssue).join(",")})`;    default:      return issue._tag;  }} // ===============================// Core Persistence Errors// =============================== export const PersistenceErrorCorrelation = Schema.Union([  Schema.Struct({ sessionId: Schema.String }),  Schema.Struct({ currentSessionId: Schema.String }),  Schema.Struct({ pairingLinkId: Schema.String }),  Schema.Struct({ threadId: Schema.String }),]);export type PersistenceErrorCorrelation = typeof PersistenceErrorCorrelation.Type; export class PersistenceSqlError extends Schema.TaggedError<PersistenceSqlError>()(  "PersistenceSqlError",  {    operation: Schema.String,    detail: Schema.optional(Schema.String),    correlation: Schema.optional(PersistenceErrorCorrelation),    cause: Schema.optional(Schema.Defect()),  },) {  override get message(): string {    return this.detail === undefined      ? `SQL error in ${this.operation}`      : `SQL error in ${this.operation}: ${this.detail}`;  }} export class PersistenceDecodeError extends Schema.TaggedError<PersistenceDecodeError>()(  "PersistenceDecodeError",  {    operation: Schema.String,    issue: Schema.String,    correlation: Schema.optional(PersistenceErrorCorrelation),    cause: Schema.optional(Schema.Defect()),  },) {  static fromSchemaError(    operation: string,    cause: Schema.SchemaError,    correlation?: PersistenceErrorCorrelation,  ): PersistenceDecodeError {    return new PersistenceDecodeError({      operation,      issue: summarizeSchemaIssue(cause.issue),      ...(correlation === undefined ? {} : { correlation }),      cause,    });  }   override get message(): string {    return `Decode error in ${this.operation}: ${this.issue}`;  }}const isPersistenceSqlError = Schema.is(PersistenceSqlError);const isPersistenceDecodeError = Schema.is(PersistenceDecodeError); /** * Read a SQLite condition through SQL error wrappers. * Use Node's fixed description or Bun's numeric code, never the driver message. */function sqliteCondition(cause: unknown): string | undefined {  let value = cause;  for (let depth = 0; depth < 4 && Predicate.isObject(value); depth += 1) {    if (      "errcode" in value &&      typeof value.errcode === "number" &&      "errstr" in value &&      typeof value.errstr === "string"    ) {      return `SQLITE(${value.errcode}) ${value.errstr}`;    }    if (      "name" in value &&      value.name === "SQLiteError" &&      "errno" in value &&      typeof value.errno === "number" &&      Number.isInteger(value.errno)    ) {      return `SQLITE(${value.errno})`;    }    value = "cause" in value ? value.cause : undefined;  }  return undefined;} /** * A rejected payload must never reach diagnostics, so a schema failure * contributes only its issue tags, and a driver failure only its normalized * condition. Anything the mapper cannot categorize leaves the detail unset. */function describeSqlCause(cause: unknown): string | undefined {  if (Schema.isSchemaError(cause)) return summarizeSchemaIssue(cause.issue);  return sqliteCondition(cause);} // Kept for orchestration/projection call sites, which are being revamped separately.export function toPersistenceSqlError(operation: string) {  return (cause: unknown): PersistenceSqlError => {    const detail = describeSqlCause(cause);    return new PersistenceSqlError({      operation,      ...(detail === undefined ? {} : { detail }),      cause,    });  };} // Kept for orchestration/projection call sites, which are being revamped separately.export function toPersistenceDecodeError(operation: string) {  return (cause: Schema.SchemaError): PersistenceDecodeError =>    PersistenceDecodeError.fromSchemaError(operation, cause);} export const isPersistenceError = (u: unknown) =>  isPersistenceSqlError(u) || isPersistenceDecodeError(u); // ===============================// Provider Session Repository Errors// =============================== export class ProviderSessionRepositoryValidationError extends Schema.TaggedError<ProviderSessionRepositoryValidationError>()(  "ProviderSessionRepositoryValidationError",  {    operation: Schema.String,    issue: Schema.String,    cause: Schema.optional(Schema.Defect()),  },) {  override get message(): string {    return `Provider session repository validation failed in ${this.operation}: ${this.issue}`;  }} export class ProviderSessionRepositoryPersistenceError extends Schema.TaggedError<ProviderSessionRepositoryPersistenceError>()(  "ProviderSessionRepositoryPersistenceError",  {    operation: Schema.String,    detail: Schema.String,    cause: Schema.optional(Schema.Defect()),  },) {  override get message(): string {    return `Provider session repository persistence error in ${this.operation}: ${this.detail}`;  }} export type OrchestrationEventStoreError = PersistenceSqlError | PersistenceDecodeError; export type ProviderSessionRepositoryError =  | ProviderSessionRepositoryValidationError  | ProviderSessionRepositoryPersistenceError; export type OrchestrationCommandReceiptRepositoryError =  | PersistenceSqlError  | PersistenceDecodeError; export type ProviderSessionRuntimeRepositoryError = PersistenceSqlError | PersistenceDecodeError;export type AuthPairingLinkRepositoryError = PersistenceSqlError | PersistenceDecodeError;export type AuthSessionRepositoryError = PersistenceSqlError | PersistenceDecodeError; export type ProjectionRepositoryError = PersistenceSqlError | PersistenceDecodeError;