diff --git a/src/createMollieClient.ts b/src/createMollieClient.ts index 5a2d1968..60be6828 100644 --- a/src/createMollieClient.ts +++ b/src/createMollieClient.ts @@ -31,25 +31,29 @@ import RefundsResource from './resources/refunds/RefundsResource'; import SubscriptionsResource from './resources/subscriptions/SubscriptionsResource'; import SubscriptionsPaymentsResource from './resources/subscriptions/payments/SubscriptionsPaymentsResource'; -export type MollieOptions = AxiosRequestConfig & { +export type MollieOptions = Xor< + { + /** + * The Mollie API key, starting with `'test_'` or `'live_'`. + */ + apiKey: string; + }, + { + /** + * OAuth access token, starting with `'access_''. + */ + accessToken: string; + } +> & { /** * One or an array of version strings of the software you are using, such as `'RockenbergCommerce/3.1.12'`. */ versionStrings?: string | string[]; -} & Xor< - { - /** - * The Mollie API key, starting with `'test_'` or `'live_'`. - */ - apiKey: string; - }, - { - /** - * OAuth access token, starting with `'access_''. - */ - accessToken: string; - } - >; + /** + * The URL of the root of the Mollie API. Default: `'https://api.mollie.com:443/v2/'`. + */ + apiEndpoint?: string; +} & Pick; function preprocessVersionStrings(input: string | string[] | undefined): string[] { if (Array.isArray(input)) { @@ -60,14 +64,10 @@ function preprocessVersionStrings(input: string | string[] | undefined): string[ } return []; } -function createHttpClient({ apiKey, accessToken, versionStrings, ...axiosOptions }: MollieOptions): AxiosInstance { - axiosOptions.baseURL = 'https://api.mollie.com:443/v2/'; - - if (axiosOptions.headers == undefined) { - axiosOptions.headers = {}; - } +function createHttpClient({ apiKey, accessToken, versionStrings, apiEndpoint = 'https://api.mollie.com:443/v2/', ...axiosOptions }: MollieOptions): AxiosInstance { + const headers: Record = axiosOptions.headers ?? {}; - axiosOptions.headers['User-Agent'] = [ + headers['User-Agent'] = [ `Node/${process.version}`, `Mollie/${libraryVersion}`, ...preprocessVersionStrings(versionStrings).map(versionString => { @@ -91,19 +91,22 @@ function createHttpClient({ apiKey, accessToken, versionStrings, ...axiosOptions ].join(' '); if (apiKey != undefined) { - axiosOptions.headers['Authorization'] = `Bearer ${apiKey}`; + headers['Authorization'] = `Bearer ${apiKey}`; } /* if (accessToken != undefined) */ else { - axiosOptions.headers['Authorization'] = `Bearer ${accessToken}`; - axiosOptions.headers['User-Agent'] += ' OAuth/2.0'; + headers['Authorization'] = `Bearer ${accessToken}`; + headers['User-Agent'] += ' OAuth/2.0'; } - axiosOptions.headers['Accept-Encoding'] = 'gzip'; - axiosOptions.headers['Content-Type'] = 'application/json'; - - axiosOptions.httpsAgent = new https.Agent({ - ca: caCertificates, + headers['Accept-Encoding'] = 'gzip'; + headers['Content-Type'] = 'application/json'; + + return axios.create({ + ...axiosOptions, + baseURL: apiEndpoint, + headers, + httpsAgent: new https.Agent({ + ca: caCertificates, + }), }); - - return axios.create(axiosOptions); } /** @@ -112,7 +115,7 @@ function createHttpClient({ apiKey, accessToken, versionStrings, ...axiosOptions */ export default function createMollieClient(options: MollieOptions) { // Attempt to catch cases where this library is integrated into a frontend app. - if (['node', 'io.js'].indexOf(process?.release?.name) == -1) { + if (['node', 'io.js'].includes(process?.release?.name) == false) { throw new Error( `Unexpected process release name ${process?.release?.name}. This may indicate that the Mollie API client is integrated into a website or app. This is not recommended, please see https://github.com/mollie/mollie-api-node/#a-note-on-use-outside-of-nodejs. If this is a mistake, please let us know: https://github.com/mollie/mollie-api-node/issues`, ); diff --git a/tests/unit/networking.test.ts b/tests/unit/networking.test.ts index cfa8d81a..f2c8185c 100644 --- a/tests/unit/networking.test.ts +++ b/tests/unit/networking.test.ts @@ -40,7 +40,7 @@ test('defaults', async () => { }); async function requestWithVersionStrings(versionStrings: string | string[] | undefined) { - const { adapter, client } = wireMockClient(versionStrings); + const { adapter, client } = wireMockClient({ versionStrings }); adapter.onGet('/customers').reply(200, { _embedded: { @@ -91,3 +91,30 @@ test('customVersionStrings', async () => { expect(headers['User-Agent'].endsWith('phpCookbookForNodeUsers/7.3.4')).toBe(true); }); + +test('customApiEndpoint', async () => { + const { adapter, client } = wireMockClient({ apiEndpoint: 'https://null.house/' }); + + adapter.onGet('/customers').reply(200, { + _embedded: { + customers: [], + }, + count: 0, + _links: { + documentation: { + href: 'https://docs.mollie.com/reference/v2/customers-api/list-customers', + type: 'text/html', + }, + self: { + href: 'https://api.mollie.com/v2/customers?limit=50', + type: 'application/hal+json', + }, + previous: null, + next: null, + }, + }); + + await bluster(client.customers.all.bind(client.customers))(); + + expect(adapter.history.get[0].baseURL).toBe('https://null.house/'); +}); diff --git a/tests/wireMockClient.ts b/tests/wireMockClient.ts index aa09a48f..43ff74e9 100644 --- a/tests/wireMockClient.ts +++ b/tests/wireMockClient.ts @@ -1,16 +1,16 @@ -import createMollieClient, { MollieClient } from '..'; +import createMollieClient, { MollieClient, MollieOptions } from '..'; import { AxiosInstance } from 'axios'; import MockAdapter from 'axios-mock-adapter'; import {} from 'jest-bluster'; -export default function wireMockClient(versionStrings?: string | string[]): { adapter: MockAdapter; client: MollieClient } { +export default function wireMockClient(options?: Omit): { adapter: MockAdapter; client: MollieClient } { const adapter = new MockAdapter((undefined as unknown) as AxiosInstance); return { adapter, client: createMollieClient({ apiKey: 'mock-api-key', adapter: adapter.adapter(), - versionStrings, + ...options, }), }; }