1- import { PaystackError , getPaystackRequestId } from "./errors.js" ;
1+ import { PaystackError , getPaystackRequestId , type PaystackErrorType } from "./errors.js" ;
22
33/**
44 * Base structure of a Paystack API response body
@@ -7,7 +7,53 @@ export interface PaystackRawResponse<T = unknown> {
77 status : boolean ;
88 message : string ;
99 data : T ;
10+ code ?: string ;
11+ type ?: PaystackErrorType ;
1012 meta ?: Record < string , unknown > ;
13+ errorCodeMappingNotFound ?: boolean ;
14+ }
15+
16+ interface PaystackErrorEnvelope {
17+ message ?: string ;
18+ code ?: string ;
19+ type ?: PaystackErrorType ;
20+ meta ?: Record < string , unknown > ;
21+ }
22+
23+ function isRecord ( value : unknown ) : value is Record < string , unknown > {
24+ return typeof value === "object" && value !== null ;
25+ }
26+
27+ function getStringField ( source : unknown , field : string ) : string | undefined {
28+ if ( ! isRecord ( source ) ) return undefined ;
29+ const value = source [ field ] ;
30+ return typeof value === "string" && value !== "" ? value : undefined ;
31+ }
32+
33+ function getMeta ( source : unknown ) : Record < string , unknown > | undefined {
34+ if ( ! isRecord ( source ) ) return undefined ;
35+ const value = source . meta ;
36+ return isRecord ( value ) ? value : undefined ;
37+ }
38+
39+ function getPaystackEnvelope ( source : unknown ) : PaystackErrorEnvelope {
40+ return {
41+ message : getStringField ( source , "message" ) ,
42+ code : getStringField ( source , "code" ) ,
43+ type : getStringField ( source , "type" ) as PaystackErrorType | undefined ,
44+ meta : getMeta ( source ) ,
45+ } ;
46+ }
47+
48+ function resolveErrorMessage ( error : unknown , raw : unknown ) : string {
49+ const errorEnvelope = getPaystackEnvelope ( error ) ;
50+ if ( errorEnvelope . message !== undefined ) return errorEnvelope . message ;
51+
52+ const rawEnvelope = getPaystackEnvelope ( raw ) ;
53+ if ( rawEnvelope . message !== undefined ) return rawEnvelope . message ;
54+
55+ if ( error instanceof Error && error . message !== "" ) return error . message ;
56+ return "Network or HTTP Error" ;
1157}
1258
1359/**
@@ -48,19 +94,19 @@ export class PaystackResponse<T> {
4894 const requestId = getPaystackRequestId ( this . response . headers ) ;
4995
5096 if ( this . error !== undefined && this . error !== null ) {
51- // Handle HTTP or Network errors
52- let message = "Network or HTTP Error" ;
53- if ( typeof this . error === "object" && this . error !== null && "message" in this . error ) {
54- message = String ( ( this . error as { message : unknown } ) . message ) ;
55- } else if ( this . raw && typeof this . raw === "object" && "message" in this . raw ) {
56- message = this . raw . message ;
57- }
97+ const errorEnvelope = getPaystackEnvelope ( this . error ) ;
98+ const rawEnvelope = getPaystackEnvelope ( this . raw ) ;
5899
59100 throw new PaystackError ( {
60- message,
101+ message : resolveErrorMessage ( this . error , this . raw ) ,
102+ code : errorEnvelope . code ?? rawEnvelope . code ,
103+ type : errorEnvelope . type ?? rawEnvelope . type ,
61104 status : this . response . status ,
62105 requestId,
63- meta : this . raw ?. meta ,
106+ meta : errorEnvelope . meta ?? rawEnvelope . meta ,
107+ raw : this . error ,
108+ body : this . error ,
109+ cause : this . error ,
64110 } ) ;
65111 }
66112
@@ -70,16 +116,24 @@ export class PaystackResponse<T> {
70116 message : "Empty response body" ,
71117 status : this . response . status ,
72118 requestId,
119+ raw : this . raw ,
120+ body : this . raw ,
73121 } ) ;
74122 }
75123
76124 if ( ! this . raw . status ) {
125+ const rawEnvelope = getPaystackEnvelope ( this . raw ) ;
126+
77127 // Handle Paystack-level errors (status: false)
78128 throw new PaystackError ( {
79- message : this . raw . message ,
129+ message : rawEnvelope . message ?? "Paystack API Error" ,
130+ code : rawEnvelope . code ,
131+ type : rawEnvelope . type ,
80132 status : this . response . status ,
81133 requestId,
82- meta : this . raw . meta ,
134+ meta : rawEnvelope . meta ,
135+ raw : this . raw ,
136+ body : this . raw ,
83137 } ) ;
84138 }
85139
@@ -93,9 +147,20 @@ export class PaystackResponse<T> {
93147 * @throws {PaystackError } if status is false.
94148 */
95149 public get data ( ) : T {
96- if ( this . raw === undefined || this . raw === null ) {
97- return this . unwrap ( ) ;
98- }
99- return this . raw . data ;
150+ return this . unwrap ( ) ;
151+ }
152+ }
153+
154+ export function assertOk < T > ( result : PaystackResponse < T > ) : T {
155+ return result . unwrap ( ) ;
156+ }
157+
158+ export function toPaystackApiError < T > ( result : PaystackResponse < T > ) : PaystackError | undefined {
159+ try {
160+ result . unwrap ( ) ;
161+ return undefined ;
162+ } catch ( error ) {
163+ if ( error instanceof PaystackError ) return error ;
164+ throw error ;
100165 }
101166}
0 commit comments