All files / src/sdk WalletError.ts

69.38% Statements 34/49
60.46% Branches 26/43
57.14% Functions 4/7
74.41% Lines 32/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                                    57x   82x   82x 82x 82x 82x           27x           5x                   47x 47x   47x 47x 47x 26x   21x 47x   47x 47x   47x   47x 47x   47x           47x 47x 146x 67x 79x         21x 19x             39x 39x       47x                            
import { ErrorCodeString10To40Bytes, ErrorDescriptionString20To200Bytes } from '@bsv/sdk'
import { sdk } from "../index.client"
import { WalletErrorObject } from "./Wallet.interfaces"
 
/**
 * Derived class constructors should use the derived class name as the value for `name`,
 * and an internationalizable constant string for `message`.
 *
 * If a derived class intends to wrap another WalletError, the public property should
 * be named `walletError` and will be recovered by `fromUnknown`.
 * 
 * Optionaly, the derived class `message` can include template parameters passed in
 * to the constructor. See WERR_MISSING_PARAMETER for an example.
 *
 * To avoid derived class name colisions, packages should include a package specific
 * identifier after the 'WERR_' prefix. e.g. 'WERR_FOO_' as the prefix for Foo package error
 * classes.
 */
export class WalletError extends Error implements WalletErrorObject {
  // Facilitates detection of Error objects from non-error return values.
  isError: true = true
 
  constructor(name: string, message: string, stack?: string, public details?: Record<string, string>) {
    super(message)
    this.name = name
    if (stack) this.stack = stack
  }
 
  /**
     * Error class compatible accessor for  `code`.
     */
  get code (): ErrorCodeString10To40Bytes { return this.name }
  set code (v: ErrorCodeString10To40Bytes) { this.name = v }
 
  /**
     * Error class compatible accessor for `description`.
     */
  get description (): ErrorDescriptionString20To200Bytes { return this.message }
  set description (v: ErrorDescriptionString20To200Bytes) { this.message = v }
 
  /**
   * Recovers all public fields from WalletError derived error classes and relevant Error derived errors.
   * 
   * Critical client data fields are preserved across HTTP DojoExpress / DojoExpressClient encoding.
   */
  static fromUnknown(err: unknown): WalletError {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let name = 'WERR_UNKNOWN'
    let message = ''
    let stack: string | undefined
    const details: Record<string, string> = {}
    if (err !== null && typeof err === 'object') {
      if (err["name"] === "Error" || err["name"] === "FetchError")
        name = err["code"] || err["status"] || "WERR_UNKNOWN"
      else
        name = err["name"] || err["code"] || err["status"] || "WERR_UNKNOWN"
      Iif (typeof name !== 'string') name = "WERR_UNKNOWN"
 
      message = err["message"] || err["description"] || ''
      Iif (typeof message !== 'string') message = "WERR_UNKNOWN"
 
      if (typeof err["stack"] === 'string') stack = err["stack"]
 
      Iif (typeof err["sql"] === 'string') details.sql = err["sql"]
      Iif (typeof err["sqlMessage"] === 'string') details.sqlMessage = err["sqlMessage"]
    }
    const e = new WalletError(
      name,
      message,
      stack,
      Object.keys(details).length > 0 ? details : undefined
    )
    if (err !== null && typeof err === 'object') {
      for (const [key, value] of Object.entries(err)) {
        if (key !== 'walletError' && typeof value !== 'string' && typeof value !== 'number' && !Array.isArray(value))
          continue
        switch (key) {
          case 'walletError':
            e[key] = WalletError.fromUnknown(value);
            break
          case 'status': break
          case 'name': break
          case 'code': break
          case 'message': break
          case 'description': break
          case 'stack': break
          case 'sql': break
          case 'sqlMessage': break
          default:
            e[key] = value;
            break
        }
      }
    }
    return e
  }
 
  /**
   * @returns standard HTTP error status object with status property set to 'error'.
   */
  asStatus(): { status: string, code: string, description: string } {
    return {
      status: 'error',
      code: this.name,
      description: this.message
    }
  }
}