1
1
import cheerio from 'cheerio'
2
- import got , { Response , OptionsOfTextResponseBody , Method } from 'got '
2
+ import { fetchWithRetry } from '@/frame/lib/fetch-utils '
3
3
import { omitBy , isUndefined } from 'lodash-es'
4
4
5
5
type ResponseTypes = 'buffer' | 'json' | 'text'
@@ -9,8 +9,8 @@ type ResponseTypeMap = {
9
9
text : string
10
10
}
11
11
12
- interface GetOptions < ResponseType extends ResponseTypes = 'text' , M extends Method = 'get' > {
13
- method ?: M
12
+ interface GetOptions < ResponseType extends ResponseTypes = 'text' > {
13
+ method ?: string
14
14
body ?: any
15
15
followRedirects ?: boolean
16
16
followAllRedirects ?: boolean
@@ -26,12 +26,16 @@ interface GetDOMOptions {
26
26
retries ?: number
27
27
}
28
28
29
- interface ResponseWithHeaders < T > extends Response < T > {
29
+ interface ResponseWithHeaders < T > {
30
+ body : T
31
+ statusCode : number
30
32
headers : Record < string , string >
33
+ url : string
34
+ ok : boolean
31
35
}
32
36
33
37
// Type alias for cached DOM results to improve maintainability
34
- type CachedDOMResult = cheerio . Root & { res : Response ; $ : cheerio . Root }
38
+ type CachedDOMResult = cheerio . Root & { res : ResponseWithHeaders < string > ; $ : cheerio . Root }
35
39
36
40
// Cache to store DOM objects
37
41
const getDOMCache = new Map < string , CachedDOMResult > ( )
@@ -43,43 +47,62 @@ const getDOMCache = new Map<string, CachedDOMResult>()
43
47
* @param options - Configuration options for the request.
44
48
* @returns A promise that resolves to the HTTP response.
45
49
*/
46
- export async function get < T extends ResponseTypes = 'text' , M extends Method = 'get' > (
50
+ export async function get < T extends ResponseTypes = 'text' > (
47
51
route : string ,
48
- options : GetOptions < T , M > = { } ,
52
+ options : GetOptions < T > = { } ,
49
53
) : Promise < ResponseWithHeaders < ResponseTypeMap [ T ] > > {
50
54
const {
51
55
method = 'get' ,
52
- body,
56
+ body : requestBody ,
53
57
followRedirects = false ,
54
58
followAllRedirects = false ,
55
59
headers = { } ,
56
60
responseType,
57
61
retries = 0 ,
58
62
} = options
59
63
60
- // Ensure the method is a valid function on `got`
61
- const fn = got [ method as 'get' ]
62
- if ( ! fn || typeof fn !== 'function' ) {
63
- throw new Error ( `No method function for '${ method } '` )
64
- }
65
-
66
- // Construct the options for the `got` request, omitting undefined values
67
- const xopts : OptionsOfTextResponseBody = omitBy (
64
+ // Construct the options for the fetch request
65
+ const fetchOptions : RequestInit = omitBy (
68
66
{
69
- body,
70
- headers,
71
- retry : { limit : retries } ,
72
- throwHttpErrors : false ,
73
- followRedirect : followAllRedirects || followRedirects ,
74
- responseType : responseType || undefined ,
67
+ method : method . toUpperCase ( ) ,
68
+ body : requestBody ,
69
+ headers : headers as HeadersInit ,
70
+ redirect : followAllRedirects || followRedirects ? 'follow' : 'manual' ,
75
71
} ,
76
72
isUndefined ,
77
73
)
78
74
79
75
// Perform the HTTP request
80
- return ( await fn ( `http://localhost:4000${ route } ` , xopts ) ) as ResponseWithHeaders <
81
- ResponseTypeMap [ T ]
82
- >
76
+ const response = await fetchWithRetry ( `http://localhost:4000${ route } ` , fetchOptions , {
77
+ retries,
78
+ throwHttpErrors : false ,
79
+ } )
80
+
81
+ // Get response body based on responseType
82
+ let responseBody : ResponseTypeMap [ T ]
83
+ if ( responseType === 'json' ) {
84
+ responseBody = ( await response . json ( ) ) as ResponseTypeMap [ T ]
85
+ } else if ( responseType === 'buffer' ) {
86
+ const arrayBuffer = await response . arrayBuffer ( )
87
+ responseBody = arrayBuffer as ResponseTypeMap [ T ]
88
+ } else {
89
+ responseBody = ( await response . text ( ) ) as ResponseTypeMap [ T ]
90
+ }
91
+
92
+ // Convert headers to record format
93
+ const headersRecord : Record < string , string > = { }
94
+ response . headers . forEach ( ( value , key ) => {
95
+ headersRecord [ key ] = value
96
+ } )
97
+
98
+ // Return response in got-compatible format
99
+ return {
100
+ body : responseBody ,
101
+ statusCode : response . status ,
102
+ headers : headersRecord ,
103
+ url : response . url ,
104
+ ok : response . ok ,
105
+ } as ResponseWithHeaders < ResponseTypeMap [ T ] >
83
106
}
84
107
85
108
/**
@@ -92,7 +115,7 @@ export async function get<T extends ResponseTypes = 'text', M extends Method = '
92
115
export async function head (
93
116
route : string ,
94
117
opts : { followRedirects ?: boolean } = { followRedirects : false } ,
95
- ) : Promise < Response < string > > {
118
+ ) : Promise < ResponseWithHeaders < string > > {
96
119
const res = await get ( route , { method : 'head' , followRedirects : opts . followRedirects } )
97
120
return res
98
121
}
@@ -107,7 +130,7 @@ export async function head(
107
130
export function post (
108
131
route : string ,
109
132
opts : Omit < GetOptions , 'method' > = { } ,
110
- ) : Promise < Response < string > > {
133
+ ) : Promise < ResponseWithHeaders < string > > {
111
134
return get ( route , { ...opts , method : 'post' } )
112
135
}
113
136
0 commit comments