11import type { EngineName , EngineParameters } from "./types.ts" ;
22import { version } from "../version.ts" ;
3- import fetch from "npm:cross-fetch@3.1.4" ;
4- import core from "npm:core-js-pure@3.28.0" ;
5- const { globalThis, URL , URLSearchParams } = core ;
63
74type UrlParameters = Record <
85 string ,
@@ -11,26 +8,48 @@ type UrlParameters = Record<
118
129/**
1310 * This `_internals` object is needed to support stubbing/spying of
14- * fetch, execute and getBaseUrl .
11+ * certain functions in this file .
1512 * https://deno.land/manual@v1.28.3/basics/testing/mocking
1613 *
17- * If fetch is stubbed via `globalThis`, the test phase of the npm build fails.
18- * ```ts
19- * const fetchStub = stub(globalThis, "fetch", resolvesNext([new Response("data")]));
20- * ```
21- *
22- * [`dnt`](https://github.com/denoland/dnt) shims `fetch` by relying on the
23- * `undici` package. It replaces all references to `fetch` with `dntShim.fetch`.
24- * As a side effect, stubbing `globalThis.fetch` becomes incorrect; we want to
25- * stub `dntShim.fetch` instead.
26- *
27- * As a workaround, the `_internals` object serves as an indirection and we
28- * stub the `fetch` key of this object instead.
14+ * It's also useful to encapsulate functions that are polyfilled.
2915 */
3016export const _internals = {
31- fetch : fetch ,
17+ get fetch ( ) {
18+ return ( async ( ) => {
19+ // Use runtime's `fetch` if it exists, otherwise fallback to `cross-fetch`.
20+ return typeof fetch === "function"
21+ ? Promise . resolve ( fetch )
22+ : ( await import ( "npm:cross-fetch@3.1.4" ) ) . default ;
23+ } ) ( ) ;
24+ } ,
3225 execute : execute ,
3326 getBaseUrl : getBaseUrl ,
27+ get globalThis ( ) {
28+ return ( async ( ) => {
29+ // Use runtime's `globalThis` if it exists, otherwise fallback to `core-js`'s implementation.
30+ // dnt-shim-ignore
31+ const gt = typeof globalThis !== "undefined" ? globalThis : undefined ;
32+ return gt !== undefined
33+ ? Promise . resolve ( gt )
34+ : ( await import ( "npm:core-js-pure@3.28.0" ) ) . default . globalThis ;
35+ } ) ( ) ;
36+ } ,
37+ get URL ( ) : Promise < typeof URL > {
38+ return ( async ( ) => {
39+ // Use runtime's `URL` if it exists, otherwise fallback to `core-js`'s implementation.
40+ return typeof URL !== "undefined"
41+ ? Promise . resolve ( URL )
42+ : ( await import ( "npm:core-js-pure@3.28.0" ) ) . default . URL ;
43+ } ) ( ) ;
44+ } ,
45+ get URLSearchParams ( ) : Promise < typeof URLSearchParams > {
46+ return ( async ( ) => {
47+ // Use runtime's `URLSearchParams` if it exists, otherwise fallback to `core-js`'s implementation.
48+ return typeof URLSearchParams !== "undefined"
49+ ? Promise . resolve ( URLSearchParams )
50+ : ( await import ( "npm:core-js-pure@3.28.0" ) ) . default . URLSearchParams ;
51+ } ) ( ) ;
52+ } ,
3453} ;
3554
3655/** Facilitates stubbing in tests, e.g. localhost as the base url */
@@ -46,14 +65,17 @@ type NextParameters<E extends EngineName = EngineName> = {
4665 >
4766 ] : string ;
4867} ;
49- export function extractNextParameters < E extends EngineName = EngineName > ( json : {
50- serpapi_pagination ?: { next : string } ;
51- pagination ?: { next : string } ;
52- } ) {
68+ export async function extractNextParameters < E extends EngineName = EngineName > (
69+ json : {
70+ serpapi_pagination ?: { next : string } ;
71+ pagination ?: { next : string } ;
72+ } ,
73+ ) {
5374 const nextUrlString = json [ "serpapi_pagination" ] ?. [ "next" ] ||
5475 json [ "pagination" ] ?. [ "next" ] ;
5576
5677 if ( nextUrlString ) {
78+ const URL = await _internals . URL ;
5779 const nextUrl = new URL ( nextUrlString ) ;
5880 const nextParameters : Record < string , string > = { } ;
5981 for ( const [ k , v ] of nextUrl . searchParams . entries ( ) ) {
@@ -78,22 +100,20 @@ export function haveParametersChanged(
78100 ) ;
79101}
80102
81- function getSource ( ) {
103+ export async function getSource ( ) {
82104 const moduleSource = `serpapi@${ version } ` ;
83105 try {
106+ const gt = await _internals . globalThis ;
107+
84108 // Check if running in Node.js
85- // dnt-shim-ignore
86- // deno-lint-ignore no-explicit-any
87- const nodeVersion = ( globalThis as any ) . process ?. versions ?. node ;
109+ const nodeVersion = gt . process ?. versions ?. node ;
88110 if ( nodeVersion ) {
89111 return `nodejs@${ nodeVersion } ,${ moduleSource } ` ;
90112 }
91113
92114 // Assumes running in Deno instead. https://deno.land/api?s=Deno.version
93115 // Deno.version is not shimmed since it's not used when ran in a Node env.
94- // dnt-shim-ignore
95- // deno-lint-ignore no-explicit-any
96- const denoVersion = ( globalThis as any ) . Deno ?. version ?. deno ;
116+ const denoVersion = gt . Deno ?. version ?. deno ;
97117 if ( denoVersion ) {
98118 return `deno@${ denoVersion } ,${ moduleSource } ` ;
99119 }
@@ -105,37 +125,40 @@ function getSource() {
105125 }
106126}
107127
108- export function buildUrl < P extends UrlParameters > (
128+ export async function buildUrl < P extends UrlParameters > (
109129 path : string ,
110130 parameters : P ,
111- ) : string {
131+ ) : Promise < string > {
112132 const nonUndefinedParams : [ string , string ] [ ] = Object . entries ( parameters )
113133 . filter ( ( [ _ , value ] ) => value !== undefined )
114134 . map ( ( [ key , value ] ) => [ key , `${ value } ` ] ) ;
135+ const URLSearchParams = await _internals . URLSearchParams ;
115136 const searchParams = new URLSearchParams ( nonUndefinedParams ) ;
116137 return `${ _internals . getBaseUrl ( ) } ${ path } ?${ searchParams } ` ;
117138}
118139
119- export function execute < P extends UrlParameters > (
140+ export async function execute < P extends UrlParameters > (
120141 path : string ,
121142 parameters : P ,
122143 timeout : number ,
123144) : Promise < Response > {
124- const url = buildUrl ( path , {
145+ const url = await buildUrl ( path , {
125146 ...parameters ,
126- source : getSource ( ) ,
147+ source : await getSource ( ) ,
127148 } ) ;
128149 // https://github.com/github/fetch/issues/175#issuecomment-216791333
129150 return new Promise ( ( resolve , reject ) => {
130151 const timer = setTimeout ( ( ) => reject ( new Error ( "Timeout" ) ) , timeout ) ;
131- _internals . fetch ( url )
132- . then ( ( res ) => {
133- clearTimeout ( timer ) ;
134- resolve ( res ) ;
135- } )
136- . catch ( ( err ) => {
137- clearTimeout ( timer ) ;
138- reject ( err ) ;
139- } ) ;
152+ _internals . fetch . then ( ( fetch ) =>
153+ fetch ( url )
154+ . then ( ( res ) => {
155+ clearTimeout ( timer ) ;
156+ resolve ( res ) ;
157+ } )
158+ . catch ( ( err ) => {
159+ clearTimeout ( timer ) ;
160+ reject ( err ) ;
161+ } )
162+ ) ;
140163 } ) ;
141164}
0 commit comments