11import { DataSource , DataSourceConfig } from 'apollo-datasource'
2- import { Client , Pool } from 'undici'
2+ import { Pool } from 'undici'
33import { STATUS_CODES } from 'http'
44import QuickLRU from '@alloc/quick-lru'
55import sjson from 'secure-json-parse'
6- import AbortController from 'abort-controller'
76
87import Keyv , { Store } from 'keyv'
98import { KeyValueCache } from 'apollo-server-caching'
10- import { DispatchOptions , ResponseData } from 'undici/types/dispatcher'
9+ import { ResponseData , RequestOptions as UndiciRequestOptions } from 'undici/types/dispatcher'
1110import { ApolloError } from 'apollo-server-errors'
11+ import { EventEmitter , Readable } from 'stream'
12+
13+ type AbortSignal = unknown
1214
1315export type CacheTTLOptions = {
1416 requestCache ?: {
@@ -19,9 +21,19 @@ export type CacheTTLOptions = {
1921 }
2022}
2123
22- export type ClientRequestOptions = Omit < DispatchOptions , 'origin' | 'path' | 'method' > & CacheTTLOptions
24+ interface Dictionary < T > {
25+ [ Key : string ] : T
26+ }
2327
24- export type RequestOptions = DispatchOptions & CacheTTLOptions
28+ export type RequestOptions = {
29+ body ?: string | Buffer | Uint8Array | Readable | null
30+ headers ?: Dictionary < string >
31+ signal ?: AbortSignal | EventEmitter | null
32+ } & CacheTTLOptions
33+
34+ export type Request = UndiciRequestOptions & CacheTTLOptions & {
35+ headers : Dictionary < string >
36+ }
2537
2638export type Response < TResult > = {
2739 body : TResult
@@ -34,8 +46,8 @@ export interface LRUOptions {
3446
3547export interface HTTPDataSourceOptions {
3648 pool ?: Pool
37- requestOptions ?: ClientRequestOptions
38- clientOptions ?: Client . Options
49+ requestOptions ?: RequestOptions
50+ clientOptions ?: Pool . Options
3951 lru ?: Partial < LRUOptions >
4052}
4153
@@ -73,9 +85,8 @@ const cacheableStatusCodes = [200, 201, 202, 203, 206]
7385export abstract class HTTPDataSource < TContext = any > extends DataSource {
7486 public context ! : TContext
7587 private storageAdapter ! : Keyv
76- private readonly pool : Pool
77- private readonly globalRequestOptions ?: ClientRequestOptions
78- private readonly abortController : AbortController
88+ private pool : Pool
89+ private globalRequestOptions ?: RequestOptions
7990 private readonly memoizedResults : QuickLRU < string , Response < any > >
8091
8192 constructor ( public readonly baseURL : string , private readonly options ?: HTTPDataSourceOptions ) {
@@ -85,7 +96,6 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
8596 } )
8697 this . pool = options ?. pool ?? new Pool ( this . baseURL , options ?. clientOptions )
8798 this . globalRequestOptions = options ?. requestOptions
88- this . abortController = new AbortController ( )
8999 }
90100
91101 /**
@@ -100,22 +110,15 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
100110 } )
101111 }
102112
103- /**
104- * Abort and signal to any request that the associated activity is to be aborted.
105- */
106- abort ( ) {
107- this . abortController . abort ( )
108- }
109-
110113 protected isResponseOk ( statusCode : number ) : boolean {
111114 return ( statusCode >= 200 && statusCode <= 399 ) || statusCode === 304
112115 }
113116
114117 protected isResponseCacheable < TResult = unknown > (
115- requestOptions : RequestOptions ,
118+ request : Request ,
116119 response : Response < TResult > ,
117120 ) : boolean {
118- return cacheableStatusCodes . indexOf ( response . statusCode ) > - 1 && requestOptions . method === 'GET'
121+ return cacheableStatusCodes . indexOf ( response . statusCode ) > - 1 && request . method === 'GET'
119122 }
120123
121124 /**
@@ -125,8 +128,8 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
125128 * @param request
126129 * @returns
127130 */
128- protected onCacheKeyCalculation ( requestOptions : RequestOptions ) : string {
129- return requestOptions . origin + requestOptions . path
131+ protected onCacheKeyCalculation ( request : Request ) : string {
132+ return request . origin + request . path
130133 }
131134
132135 /**
@@ -135,17 +138,17 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
135138 *
136139 * @param request
137140 */
138- protected onRequest ?( requestOptions : RequestOptions ) : void
141+ protected onRequest ?( request : Request ) : void
139142
140143 /**
141144 * onResponse is executed when a response has been received.
142145 * By default the implementation will throw for for unsuccessful responses.
143146 *
144- * @param _requestOptions
147+ * @param _request
145148 * @param response
146149 */
147150 protected onResponse < TResult = unknown > (
148- _requestOptions : RequestOptions ,
151+ _request : Request ,
149152 response : Response < TResult > ,
150153 ) : Response < TResult > {
151154 if ( this . isResponseOk ( response . statusCode ) ) {
@@ -158,13 +161,14 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
158161 )
159162 }
160163
161- protected onError ?( _error : Error , requestOptions : RequestOptions ) : void
164+ protected onError ?( _error : Error , requestOptions : Request ) : void
162165
163166 protected async get < TResult = unknown > (
164167 path : string ,
165- requestOptions ?: ClientRequestOptions ,
168+ requestOptions ?: RequestOptions ,
166169 ) : Promise < Response < TResult > > {
167170 return await this . request < TResult > ( {
171+ headers : { } ,
168172 ...requestOptions ,
169173 method : 'GET' ,
170174 path,
@@ -174,9 +178,10 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
174178
175179 protected async post < TResult = unknown > (
176180 path : string ,
177- requestOptions ?: ClientRequestOptions ,
181+ requestOptions ?: RequestOptions ,
178182 ) : Promise < Response < TResult > > {
179183 return await this . request < TResult > ( {
184+ headers : { } ,
180185 ...requestOptions ,
181186 method : 'POST' ,
182187 path,
@@ -186,9 +191,10 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
186191
187192 protected async delete < TResult = unknown > (
188193 path : string ,
189- requestOptions ?: ClientRequestOptions ,
194+ requestOptions ?: RequestOptions ,
190195 ) : Promise < Response < TResult > > {
191196 return await this . request < TResult > ( {
197+ headers : { } ,
192198 ...requestOptions ,
193199 method : 'DELETE' ,
194200 path,
@@ -198,9 +204,10 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
198204
199205 protected async put < TResult = unknown > (
200206 path : string ,
201- requestOptions ?: ClientRequestOptions ,
207+ requestOptions ?: RequestOptions ,
202208 ) : Promise < Response < TResult > > {
203209 return await this . request < TResult > ( {
210+ headers : { } ,
204211 ...requestOptions ,
205212 method : 'PUT' ,
206213 path,
@@ -209,7 +216,7 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
209216 }
210217
211218 private async performRequest < TResult > (
212- options : RequestOptions ,
219+ options : Request ,
213220 cacheKey : string ,
214221 ) : Promise < Response < TResult > > {
215222 this . onRequest ?.( options )
@@ -261,14 +268,12 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
261268 }
262269 }
263270
264- private async request < TResult = unknown > (
265- requestOptions : RequestOptions ,
266- ) : Promise < Response < TResult > > {
267- const cacheKey = this . onCacheKeyCalculation ( requestOptions )
268- const ttlCacheEnabled = requestOptions . requestCache
271+ private async request < TResult = unknown > ( request : Request ) : Promise < Response < TResult > > {
272+ const cacheKey = this . onCacheKeyCalculation ( request )
273+ const ttlCacheEnabled = request . requestCache
269274
270275 // check if we have any GET call in the cache and respond immediatly
271- if ( requestOptions . method === 'GET' && ttlCacheEnabled ) {
276+ if ( request . method === 'GET' && ttlCacheEnabled ) {
272277 const cachedResponse = await this . storageAdapter . get ( cacheKey )
273278 if ( cachedResponse ) {
274279 return cachedResponse
@@ -277,8 +282,7 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
277282
278283 const options = {
279284 ...this . globalRequestOptions ,
280- ...requestOptions ,
281- signal : this . abortController . signal ,
285+ ...request ,
282286 }
283287
284288 // Memoize GET calls for the same data source instance
0 commit comments