@@ -3,19 +3,15 @@ import * as https from "node:https";
33import { TextDecoder } from "node:util" ;
44import { fromDefaultChain } from "./auth/fromChain" ;
55import { fetch } from "./fetch" ;
6- import { NamedLogger , loggerInstance , logOpId , withLogContext } from "./logging" ;
7- import { CancellationToken } from "./types " ;
6+ import { ExposedLoggers , Utils , withLogContext } from "./logging" ;
7+ import { context , Context } from "./context " ;
88
99const sdkVersion = require ( "../package.json" ) . version ;
1010
1111type HttpMethod = "POST" | "GET" | "DELETE" | "PATCH" | "PUT" ;
1212
1313export class HttpError extends Error {
14- constructor (
15- readonly message : string ,
16- readonly code : number ,
17- readonly json ?: any
18- ) {
14+ constructor ( readonly message : string , readonly code : number ) {
1915 super ( message ) ;
2016 }
2117}
@@ -26,6 +22,21 @@ export class ApiClientResponseError extends Error {
2622 }
2723}
2824
25+ function logAndReturnError (
26+ url : URL ,
27+ request : any ,
28+ response : any ,
29+ error : unknown ,
30+ context ?: Context
31+ ) {
32+ context ?. logger ?. error ( url . toString ( ) , {
33+ request,
34+ response,
35+ error : Utils . liftAllErrorProps ( error ) ,
36+ } ) ;
37+ return error ;
38+ }
39+
2940export class ApiClient {
3041 private agent : https . Agent ;
3142 private _host ?: URL ;
@@ -63,14 +74,12 @@ export class ApiClient {
6374 return pairs . join ( " " ) ;
6475 }
6576
66- @withLogContext ( " SDK" )
77+ @withLogContext ( ExposedLoggers . SDK )
6778 async request (
6879 path : string ,
6980 method : HttpMethod ,
7081 payload ?: any ,
71- cancellationToken ?: CancellationToken ,
72- @logOpId ( ) opId ?: string ,
73- @loggerInstance ( ) logger ?: NamedLogger
82+ @context context ?: Context
7483 ) : Promise < Object > {
7584 const credentials = await this . credentialProvider ( ) ;
7685 const headers = {
@@ -100,57 +109,71 @@ export class ApiClient {
100109 let response ;
101110
102111 try {
103- logger ?. debug ( url . toString ( ) , { request : options } ) ;
104112 const { abort, response : responsePromise } = await fetch (
105113 url . toString ( ) ,
106114 options
107115 ) ;
108- if ( cancellationToken ?. onCancellationRequested ) {
109- cancellationToken ?. onCancellationRequested ( abort ) ;
116+ if ( context ?. cancellationToken ?. onCancellationRequested ) {
117+ context ?. cancellationToken ?. onCancellationRequested ( abort ) ;
110118 }
111119 response = await responsePromise ;
112120 } catch ( e : any ) {
113- if ( e . code && e . code === "ENOTFOUND" ) {
114- throw new HttpError ( `Can't connect to ${ url . toString ( ) } ` , 500 ) ;
115- } else {
116- throw e ;
117- }
121+ const err =
122+ e . code && e . code === "ENOTFOUND"
123+ ? new HttpError ( `Can't connect to ${ url . toString ( ) } ` , 500 )
124+ : e ;
125+ throw logAndReturnError ( url , options , response , err , context ) ;
118126 }
119127
120128 // throw error if the URL is incorrect and we get back an HTML page
121129 if ( response . headers . get ( "content-type" ) ?. match ( "text/html" ) ) {
122- throw new HttpError ( `Can't connect to ${ url . toString ( ) } ` , 404 ) ;
130+ throw logAndReturnError (
131+ url ,
132+ options ,
133+ response ,
134+ new HttpError ( `Can't connect to ${ url . toString ( ) } ` , 404 ) ,
135+ context
136+ ) ;
123137 }
124138
125139 let responseBody = await response . arrayBuffer ( ) ;
126140 let responseText = new TextDecoder ( ) . decode ( responseBody ) ;
127141
128142 // TODO proper error handling
129143 if ( ! response . ok ) {
130- if ( responseText . match ( / i n v a l i d a c c e s s t o k e n / i) ) {
131- throw new HttpError ( "Invalid access token" , response . status ) ;
132- } else {
133- throw new HttpError ( responseText , response . status ) ;
134- }
144+ const err = responseText . match ( / i n v a l i d a c c e s s t o k e n / i)
145+ ? new HttpError ( "Invalid access token" , response . status )
146+ : new HttpError ( responseText , response . status ) ;
147+ throw logAndReturnError ( url , options , responseText , err , context ) ;
135148 }
136149
137150 try {
138151 response = JSON . parse ( responseText ) ;
139- logger ?. debug ( url . toString ( ) , { response : response } ) ;
140152 } catch ( e ) {
141- throw new ApiClientResponseError ( responseText , response ) ;
153+ logAndReturnError ( url , options , responseText , e , context ) ;
154+ new ApiClientResponseError ( responseText , response ) ;
142155 }
143156
144157 if ( "error" in response ) {
158+ logAndReturnError ( url , options , response , response . error , context ) ;
145159 throw new ApiClientResponseError ( response . error , response ) ;
146160 }
147161
148162 if ( "error_code" in response ) {
149163 let message =
150164 response . message || `HTTP error ${ response . error_code } ` ;
151- throw new HttpError ( message , response . error_code , response ) ;
165+ throw logAndReturnError (
166+ url ,
167+ options ,
168+ response ,
169+ new HttpError ( message , response . error_code ) ,
170+ context
171+ ) ;
152172 }
153-
173+ context ?. logger ?. debug ( url . toString ( ) , {
174+ request : options ,
175+ response : response ,
176+ } ) ;
154177 return response as any ;
155178 }
156179}
0 commit comments