diff --git a/src/sdk/v4/_fetcher.ts b/src/sdk/v4/_fetcher.ts index 25d9cb1..0fceb8b 100644 --- a/src/sdk/v4/_fetcher.ts +++ b/src/sdk/v4/_fetcher.ts @@ -33,12 +33,14 @@ export const fetcher = async ( return camelizeKeys(json) as T; } - if (typeof fetch === 'undefined') { - throw new Error('fetch is not defined'); + if (typeof globalThis.fetch !== 'function') { + throw new Error( + 'Looks like there is no global fetch function. Take a look at https://quranjs.com/techniques#custom-fetcher for more info.' + ); } // if there is no fetchFn, we use the global fetch - const res = await fetch(makeUrl(url, params)); + const res = await globalThis.fetch(makeUrl(url, params)); if (!res.ok || res.status >= 400) { throw new Error(`${res.status} ${res.statusText}`); @@ -57,12 +59,14 @@ export const mergeApiOptions = ( options: MergeApiOptionsObject = {}, defaultOptions: Record = {} ) => { + const clonedOptions = { ...options }; + // we can set it to undefined because `makeUrl` will filter it out - if (options.fetchFn) options.fetchFn = undefined; + if (clonedOptions.fetchFn) clonedOptions.fetchFn = undefined; const final: Record = { ...defaultOptions, - ...options, + ...clonedOptions, }; if (final.fields) { diff --git a/test/fetchFn.test.ts b/test/fetchFn.test.ts new file mode 100644 index 0000000..b57ba1b --- /dev/null +++ b/test/fetchFn.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from 'vitest'; +import fetch from 'cross-fetch'; +import { quran } from '../src'; + +describe('Custom fetcher', () => { + it('should fail with no fetch', () => { + // @ts-expect-error - we are testing this + globalThis.fetch = undefined; + + expect(() => quran.v4.chapters.findAll()).rejects.toThrowError( + /global fetch/ + ); + }); + + it('should not fail if you pass a fetchFn', () => { + // @ts-expect-error - we are testing this + globalThis.fetch = undefined; + + expect( + quran.v4.chapters.findById('1', { + fetchFn: (url) => { + return fetch(url).then((res) => res.json()); + }, + }) + ).resolves.not.toThrow(); + }); +}); diff --git a/test/setup.ts b/test/setup.ts index 4abe764..c417650 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,13 +1,15 @@ import fetch from 'cross-fetch'; -import { beforeAll, afterEach, afterAll } from 'vitest'; +import { beforeAll, afterEach, afterAll, beforeEach } from 'vitest'; import { server } from '../mocks/server'; // Establish API mocking before all tests. beforeAll(async () => { server.listen(); +}); +beforeEach(async () => { // we do this instead of passing a fetchFn every time - global.fetch = fetch; + globalThis.fetch = fetch; }); // Reset any request handlers that we may add during the tests,