11import { DataSource , DataSourceConfig } from 'apollo-datasource'
2- import got , { Agents , HTTPError , NormalizedOptions , OptionsOfJSONResponseBody , Response } from 'got'
2+ import got , {
3+ Agents ,
4+ HTTPError ,
5+ NormalizedOptions ,
6+ OptionsOfJSONResponseBody ,
7+ RequestError ,
8+ Response ,
9+ CacheError ,
10+ UploadError ,
11+ ReadError ,
12+ MaxRedirectsError ,
13+ GotReturn as Request ,
14+ } from 'got'
315import QuickLRU from '@alloc/quick-lru'
416import AbortController from 'abort-controller'
517
@@ -11,14 +23,14 @@ import { KeyValueCache } from 'apollo-server-caching'
1123
1224const { HttpsAgent } = HttpAgent
1325
14- export type Request = OptionsOfJSONResponseBody | NormalizedOptions
26+ export type RequestOptions = OptionsOfJSONResponseBody | NormalizedOptions
1527export interface LRUOptions {
1628 readonly maxAge ?: number
1729 readonly maxSize : number
1830}
1931
2032export interface HTTPDataSourceOptions {
21- request ?: OptionsOfJSONResponseBody
33+ requestOptions ?: RequestOptions
2234 lru ?: LRUOptions
2335}
2436
@@ -97,91 +109,92 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
97109 }
98110
99111 /**
100- * DidReceiveResponse is executed after a response has been received.
112+ * onResponse is executed after a response has been received.
101113 * You can manipulate the response by returning a different response.
102114 *
103115 * @param response
104116 * @param _request
105117 * @returns
106118 */
107- protected async didReceiveResponse < TResult = unknown > (
119+ protected async onResponse < TResult = unknown > (
108120 response : Response < TResult > ,
109121 _request : Request ,
110122 ) : Promise < Response < TResult > > {
111123 return response
112124 }
113125
114126 /**
115- * CacheKey returns the key for the GET request.
127+ * onCacheKeyCalculation returns the key for the GET request.
116128 * The key is used to memoize the request in the LRU cache.
117129 *
118130 * @param request
119131 * @returns
120132 */
121- protected cacheKey ( request : Request ) : string {
122- if ( request . url ) return request . url . toString ( )
133+ protected onCacheKeyCalculation ( requestOptions : RequestOptions ) : string {
134+ if ( requestOptions . url ) return requestOptions . url . toString ( )
123135 throw new Error ( 'No Cache key provided' )
124136 }
125137
126138 /**
127- * WillSendRequest is executed before a request is made and isn't executed for memoized calls.
139+ * beforeRequest is executed before a request is made and isn't executed for memoized calls.
128140 * You can manipulate the request e.g add/remove headers.
129141 *
130142 * @param request
131143 */
132- protected willSendRequest ? ( request ?: Request ) : Promise < void >
144+ protected beforeRequest ? ( requestOptions ?: RequestOptions ) : Promise < void >
133145
134146 /**
135- * DidEncounterError is executed for any request error.
147+ * onRequestError is executed for any request error.
136148 * The raw error is passed. The thrown error might be different.
137149 *
138150 * @param _error
151+ * @param _request
139152 */
140- protected didEncounterError ( _error : Error ) { }
153+ protected onRequestError ? ( _error : Error , _request ?: Request ) : Promise < void >
141154
142155 protected async get < TResult = unknown > (
143156 url : string ,
144- request ?: Request ,
157+ requestOptions ?: RequestOptions ,
145158 ) : Promise < Response < TResult > > {
146159 return await this . request ( url , {
147160 method : 'GET' ,
148- ...request ,
161+ ...requestOptions ,
149162 } )
150163 }
151164
152165 protected async post < TResult = unknown > (
153166 url : string ,
154- request ?: Request ,
167+ requestOptions ?: RequestOptions ,
155168 ) : Promise < Response < TResult > > {
156169 return await this . request ( url , {
157170 method : 'POST' ,
158- ...request ,
171+ ...requestOptions ,
159172 } )
160173 }
161174
162175 protected async delete < TResult = unknown > (
163176 url : string ,
164- request ?: Request ,
177+ requestOptions ?: RequestOptions ,
165178 ) : Promise < Response < TResult > > {
166179 return await this . request ( url , {
167180 method : 'DELETE' ,
168- ...request ,
181+ ...requestOptions ,
169182 } )
170183 }
171184
172185 protected async put < TResult = unknown > (
173186 url : string ,
174- request ?: Request ,
187+ requestOptions ?: RequestOptions ,
175188 ) : Promise < Response < TResult > > {
176189 return await this . request ( url , {
177190 method : 'PUT' ,
178- ...request ,
191+ ...requestOptions ,
179192 } )
180193 }
181194
182195 private async performRequest < TResult > ( options : NormalizedOptions ) {
183- if ( this . willSendRequest != null ) {
184- await this . willSendRequest ( options )
196+ if ( this . beforeRequest != null ) {
197+ await this . beforeRequest ( options )
185198 }
186199
187200 const cancelableRequest = got < TResult > ( options as OptionsOfJSONResponseBody )
@@ -194,12 +207,10 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
194207
195208 try {
196209 const response = await cancelableRequest
197- return this . didReceiveResponse < TResult > ( response , options )
210+ return this . onResponse < TResult > ( response , cancelableRequest )
198211 } catch ( error ) {
199212 let error_ = error
200213
201- this . didEncounterError ( error )
202-
203214 if ( error instanceof HTTPError ) {
204215 if ( error . response . statusCode === 401 ) {
205216 error_ = new AuthenticationError ( error . message )
@@ -210,6 +221,18 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
210221 }
211222 }
212223
224+ if (
225+ this . onRequestError &&
226+ ( error instanceof RequestError ||
227+ error instanceof HTTPError ||
228+ error instanceof CacheError ||
229+ error instanceof UploadError ||
230+ error instanceof ReadError ||
231+ error instanceof MaxRedirectsError )
232+ ) {
233+ await this . onRequestError ( error , error . request )
234+ }
235+
213236 throw error_
214237 } finally {
215238 this . abortController . signal . removeEventListener ( 'abort' , abort )
@@ -218,7 +241,7 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
218241
219242 private async request < TResult = unknown > (
220243 path : string ,
221- request : Request ,
244+ requestOptions : RequestOptions ,
222245 ) : Promise < Response < TResult > > {
223246 const options = got . mergeOptions (
224247 {
@@ -230,12 +253,12 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
230253 prefixUrl : this . baseURL ,
231254 } ,
232255 {
233- ...this . options ?. request ,
256+ ...this . options ?. requestOptions ,
234257 } ,
235- request ,
258+ requestOptions ,
236259 )
237260
238- const cacheKey = this . cacheKey ( options )
261+ const cacheKey = this . onCacheKeyCalculation ( options )
239262
240263 // Memoize get call for the same data source instance
241264 // data sources are scoped to the current request
0 commit comments