Skip to content

Commit

Permalink
feat: add the ability to throttle requests (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh Fisher committed Sep 17, 2021
1 parent 2661a03 commit 9851c9f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/util/requestHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { defaultParams } from '../index';

/**
* Request helper to help with pagination for endpoints that implement the `nextCursor` functionality.
*
* Will recursively request the endpoint until the nextCursor is null and will then return a concatenated array of
* requested data.
*
* @param {T} api The INSTANCE of an api (ex. ordersApi, inventoryApi, etc)
* @param {string} methodName The name of the instanced method to use for request (ex. ordersApi.getAllOrders.name)
* @param {string} limit The limit param sent to all endpoints that require pagination
* @param {string} nextCursor Data returned from previous response to handle requesting next pagination records - Optional and should be null for first call.
*
* Note: Please use with caution. It is possible for this to be long running and quickly consume your request
* rate limits!
*
* @returns {Promise<T[]>} Array of data based on the endpoint requested
*/
const getAllRecursively = async <T>(api: T, methodName: string, limit = '100', nextCursor?: string): Promise<T[]> => {
// parse out cursor params
const nextCursorUrlParams = new URLSearchParams(nextCursor);

// convert to array for library usage
const query = [];
for (const entry of nextCursorUrlParams.entries()) {
query.push(entry);
}

const options = nextCursor && {
query,
};

// request data with cursor options if any
const ordersResponse = await api[methodName](
{
...defaultParams,
limit,
},
options
);

// recursively get new data
const { meta, elements } = ordersResponse.data.list;
let data = [...elements.order];
if (meta.nextCursor) {
const recursiveData = await getAllRecursively(api, methodName, limit, meta.nextCursor);
data = [...data, ...recursiveData];
}

// return only data and no other response props
return data;
};

export { getAllRecursively };
8 changes: 8 additions & 0 deletions tests/integration/apis/orders.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as env from '../../environment';
import walmartApi, { OrdersApi, defaultParams } from '../../../src/index';
import { addInterceptor, removeInterceptor } from '../../../utils/payload-interceptors';
import { InlineResponse200ListElementsOrderLinesOrderLineStatusesOrderLineStatusStatusEnum } from '../../../src/apis/orders';
import { getAllRecursively } from '../../../src/util/requestHelpers';

/**
* Convert order orderLines to shipping order order lines (because of course they are slightly different)
Expand Down Expand Up @@ -74,6 +75,13 @@ describe(`${OrdersApi.name}`, () => {
expect(ordersResponse.data.list.elements.order).toBeDefined();
expect(ordersResponse.data.list.elements.order).toBeInstanceOf(Array);
});

it('should recursively get all orders', async () => {
const orders = await getAllRecursively(ordersApi, ordersApi.getAllOrders.name, '100');

expect(orders).toBeDefined();
expect(orders.length).toBeGreaterThan(0);
}, 20000);
});

describe('#getAllReleasedOrders', () => {
Expand Down

0 comments on commit 9851c9f

Please sign in to comment.