Skip to content

Commit

Permalink
Add throttling to the iteration API.
Browse files Browse the repository at this point in the history
The iterate methods ‒ by default ‒ produce 500 values per minute. This hopefully discourages developers from using this API to request an unreasonable amount of values (payments/customers/…). See: #271
  • Loading branch information
Pimm committed Jul 20, 2022
1 parent 4b3c3ca commit b1ac614
Show file tree
Hide file tree
Showing 42 changed files with 193 additions and 84 deletions.
7 changes: 4 additions & 3 deletions src/binders/chargebacks/ChargebacksBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import List from '../../data/list/List';
import renege from '../../plumbing/renege';
import Callback from '../../types/Callback';
import InnerBinder from '../InnerBinder';
import { ListParameters } from './parameters';
import { IterateParameters, ListParameters } from './parameters';

const pathSegment = 'chargebacks';

Expand Down Expand Up @@ -57,7 +57,8 @@ export default class ChargebacksBinder extends InnerBinder<ChargebackData, Charg
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks
*/
public iterate(parameters?: Omit<ListParameters, 'limit'>) {
return this.networkClient.iterate<ChargebackData, Chargeback>(pathSegment, 'chargebacks', parameters);
public iterate(parameters?: IterateParameters) {
const { valuesPerMinute, ...query } = parameters ?? {};
return this.networkClient.iterate<ChargebackData, Chargeback>(pathSegment, 'chargebacks', query, valuesPerMinute);
}
}
4 changes: 3 additions & 1 deletion src/binders/chargebacks/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ChargebackEmbed } from '../../data/chargebacks/Chargeback';
import { PaginationParameters } from '../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../types/parameters';

export type ListParameters = PaginationParameters & {
embed?: ChargebackEmbed[];
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;
7 changes: 4 additions & 3 deletions src/binders/customers/CustomersBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import checkId from '../../plumbing/checkId';
import renege from '../../plumbing/renege';
import Callback from '../../types/Callback';
import Binder from '../Binder';
import { CreateParameters, DeleteParameters, GetParameters, ListParameters, UpdateParameters } from './parameters';
import { CreateParameters, DeleteParameters, GetParameters, IterateParameters, ListParameters, UpdateParameters } from './parameters';

const pathSegment = 'customers';

Expand Down Expand Up @@ -97,8 +97,9 @@ export default class CustomersBinder extends Binder<CustomerData, Customer> {
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/customers-api/list-customers
*/
public iterate(parameters?: Omit<ListParameters, 'limit'>) {
return this.networkClient.iterate<CustomerData, Customer>(pathSegment, 'customers', parameters);
public iterate(parameters?: IterateParameters) {
const { valuesPerMinute, ...query } = parameters ?? {};
return this.networkClient.iterate<CustomerData, Customer>(pathSegment, 'customers', query, valuesPerMinute);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/binders/customers/mandates/CustomerMandatesBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../../plumbing/checkId';
import renege from '../../../plumbing/renege';
import Callback from '../../../types/Callback';
import InnerBinder from '../../InnerBinder';
import { CreateParameters, GetParameters, ListParameters, RevokeParameters } from './parameters';
import { CreateParameters, GetParameters, IterateParameters, ListParameters, RevokeParameters } from './parameters';

function getPathSegments(customerId: string) {
return `customers/${customerId}/mandates`;
Expand Down Expand Up @@ -127,14 +127,14 @@ export default class CustomerMandatesBinder extends InnerBinder<MandateData, Man
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/mandates-api/list-mandates
*/
public iterate(parameters: Omit<ListParameters, 'limit'>) {
public iterate(parameters: IterateParameters) {
// parameters ?? {} is used here, because in case withParent is used, parameters could be omitted.
const customerId = this.getParentId((parameters ?? {}).customerId);
if (!checkId(customerId, 'customer')) {
throw new ApiError('The customer id is invalid');
}
const { customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<MandateData, Mandate>(getPathSegments(customerId), 'mandates', query);
const { valuesPerMinute, customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<MandateData, Mandate>(getPathSegments(customerId), 'mandates', query, valuesPerMinute);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/binders/customers/mandates/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MandateData } from '../../../data/customers/mandates/data';
import { PaginationParameters } from '../../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../../types/parameters';

interface ContextParameters {
customerId: string;
Expand Down Expand Up @@ -56,4 +56,6 @@ export type GetParameters = ContextParameters;

export type ListParameters = ContextParameters & PaginationParameters;

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;

export type RevokeParameters = ContextParameters;
4 changes: 3 additions & 1 deletion src/binders/customers/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CustomerData } from '../../data/customers/Customer';
import { PaginationParameters } from '../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../types/parameters';
import PickOptional from '../../types/PickOptional';

interface ContextParameters {
Expand All @@ -12,6 +12,8 @@ export type GetParameters = ContextParameters;

export type ListParameters = ContextParameters & PaginationParameters;

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;

export type UpdateParameters = ContextParameters & PickOptional<CustomerData, 'name' | 'email' | 'locale' | 'metadata'>;

export type DeleteParameters = ContextParameters;
8 changes: 4 additions & 4 deletions src/binders/customers/payments/CustomerPaymentsBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../../plumbing/checkId';
import renege from '../../../plumbing/renege';
import Callback from '../../../types/Callback';
import InnerBinder from '../../InnerBinder';
import { CreateParameters, ListParameters } from './parameters';
import { CreateParameters, IterateParameters, ListParameters } from './parameters';

function getPathSegments(customerId: string) {
return `customers/${customerId}/payments`;
Expand Down Expand Up @@ -85,13 +85,13 @@ export default class CustomerPaymentsBinder extends InnerBinder<PaymentData, Pay
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/customers-api/list-customer-payments
*/
public iterate(parameters: Omit<ListParameters, 'limit'>) {
public iterate(parameters: IterateParameters) {
// parameters ?? {} is used here, because in case withParent is used, parameters could be omitted.
const customerId = this.getParentId((parameters ?? {}).customerId);
if (!checkId(customerId, 'customer')) {
throw new ApiError('The customer id is invalid');
}
const { customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<PaymentData, Payment>(getPathSegments(customerId), 'payments', query);
const { valuesPerMinute, customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<PaymentData, Payment>(getPathSegments(customerId), 'payments', query, valuesPerMinute);
}
}
4 changes: 3 additions & 1 deletion src/binders/customers/payments/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PaymentMethod } from '../../../data/global';
import { PaymentData } from '../../../data/payments/data';
import { PaginationParameters } from '../../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../../types/parameters';
import PickOptional from '../../../types/PickOptional';

interface ContextParameters {
Expand All @@ -25,3 +25,5 @@ export type CreateParameters = ContextParameters &
};

export type ListParameters = ContextParameters & PaginationParameters;

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../../plumbing/checkId';
import renege from '../../../plumbing/renege';
import Callback from '../../../types/Callback';
import InnerBinder from '../../InnerBinder';
import { CancelParameters, CreateParameters, GetParameters, ListParameters, UpdateParameters } from './parameters';
import { CancelParameters, CreateParameters, GetParameters, IterateParameters, ListParameters, UpdateParameters } from './parameters';

function getPathSegments(customerId: string) {
return `customers/${customerId}/subscriptions`;
Expand Down Expand Up @@ -120,14 +120,14 @@ export default class CustomerSubscriptionsBinder extends InnerBinder<Subscriptio
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions
*/
public iterate(parameters: ListParameters) {
public iterate(parameters: IterateParameters) {
// parameters ?? {} is used here, because in case withParent is used, parameters could be omitted.
const customerId = this.getParentId((parameters ?? {}).customerId);
if (!checkId(customerId, 'customer')) {
throw new ApiError('The customer id is invalid');
}
const { customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<SubscriptionData, Subscription>(getPathSegments(customerId), 'subscriptions', query);
const { valuesPerMinute, customerId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<SubscriptionData, Subscription>(getPathSegments(customerId), 'subscriptions', query, valuesPerMinute);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/binders/customers/subscriptions/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SubscriptionData } from '../../../data/subscription/data';
import { PaginationParameters } from '../../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../../types/parameters';
import PickOptional from '../../../types/PickOptional';

interface ContextParameters {
Expand All @@ -15,6 +15,8 @@ export type GetParameters = ContextParameters;

export type ListParameters = ContextParameters & PaginationParameters;

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;

export type UpdateParameters = ContextParameters &
Pick<SubscriptionData, 'mandateId'> &
PickOptional<SubscriptionData, 'amount' | 'description' | 'interval' | 'metadata' | 'startDate' | 'times' | 'webhookUrl'>;
Expand Down
7 changes: 4 additions & 3 deletions src/binders/orders/OrdersBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../plumbing/checkId';
import renege from '../../plumbing/renege';
import Callback from '../../types/Callback';
import Binder from '../Binder';
import { CancelParameters, CreateParameters, GetParameters, ListParameters, UpdateParameters } from './parameters';
import { CancelParameters, CreateParameters, GetParameters, IterateParameters, ListParameters, UpdateParameters } from './parameters';

export const pathSegment = 'orders';

Expand Down Expand Up @@ -141,8 +141,9 @@ export default class OrdersBinder extends Binder<OrderData, Order> {
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/orders-api/list-orders
*/
public iterate(parameters?: Omit<ListParameters, 'limit'>) {
return this.networkClient.iterate<OrderData, Order>(pathSegment, 'orders', parameters);
public iterate(parameters?: IterateParameters) {
const { valuesPerMinute, ...query } = parameters ?? {};
return this.networkClient.iterate<OrderData, Order>(pathSegment, 'orders', query, valuesPerMinute);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/binders/orders/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PaymentMethod } from '../../data/global';
import { OrderAddress, OrderData, OrderEmbed } from '../../data/orders/data';
import { OrderLineData } from '../../data/orders/orderlines/OrderLine';
import { PaginationParameters } from '../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../types/parameters';
import { CreateParameters as PaymentCreateParameters } from '../payments/parameters';
import PickOptional from '../../types/PickOptional';

Expand Down Expand Up @@ -113,6 +113,8 @@ export type ListParameters = PaginationParameters & {
testmode?: boolean;
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;

export interface CancelParameters {
testmode?: boolean;
}
7 changes: 4 additions & 3 deletions src/binders/paymentLinks/PaymentLinksBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../plumbing/checkId';
import renege from '../../plumbing/renege';
import Callback from '../../types/Callback';
import Binder from '../Binder';
import { CreateParameters, GetParameters, ListParameters } from './parameters';
import { CreateParameters, GetParameters, IterateParameters, ListParameters } from './parameters';

const pathSegment = 'payment-links';

Expand Down Expand Up @@ -67,7 +67,8 @@ export default class PaymentsLinksBinder extends Binder<PaymentLinkData, Payment
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/payment-links-api/get-payment-link
*/
public iterate(parameters?: Omit<ListParameters, 'limit'>) {
return this.networkClient.iterate<PaymentLinkData, PaymentLink>(pathSegment, 'payment_links', parameters);
public iterate(parameters?: IterateParameters) {
const { valuesPerMinute, ...query } = parameters ?? {};
return this.networkClient.iterate<PaymentLinkData, PaymentLink>(pathSegment, 'payment_links', query, valuesPerMinute);
}
}
4 changes: 3 additions & 1 deletion src/binders/paymentLinks/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PaymentLinkData } from '../../data/paymentLink/data';
import { PaginationParameters } from '../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../types/parameters';

export type CreateParameters = Pick<PaymentLinkData, 'description' | 'amount' | 'redirectUrl' | 'webhookUrl' | 'expiresAt'> & {
profileId?: string;
Expand All @@ -14,3 +14,5 @@ export type ListParameters = PaginationParameters & {
profileId?: string;
testmode?: boolean;
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;
7 changes: 4 additions & 3 deletions src/binders/payments/PaymentsBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../plumbing/checkId';
import renege from '../../plumbing/renege';
import Callback from '../../types/Callback';
import Binder from '../Binder';
import { CancelParameters, CreateParameters, GetParameters, ListParameters, UpdateParameters } from './parameters';
import { CancelParameters, CreateParameters, GetParameters, IterateParameters, ListParameters, UpdateParameters } from './parameters';

const pathSegment = 'payments';

Expand Down Expand Up @@ -106,8 +106,9 @@ export default class PaymentsBinder extends Binder<PaymentData, Payment> {
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/payments-api/list-payments
*/
public iterate(parameters?: Omit<ListParameters, 'limit'>) {
return this.networkClient.iterate<PaymentData, Payment>(pathSegment, 'payments', parameters);
public iterate(parameters?: IterateParameters) {
const { valuesPerMinute, ...query } = parameters ?? {};
return this.networkClient.iterate<PaymentData, Payment>(pathSegment, 'payments', query, valuesPerMinute);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/binders/payments/captures/PaymentCapturesBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import checkId from '../../../plumbing/checkId';
import renege from '../../../plumbing/renege';
import Callback from '../../../types/Callback';
import InnerBinder from '../../InnerBinder';
import { GetParameters, ListParameters } from './parameters';
import { GetParameters, IterateParameters, ListParameters } from './parameters';

function getPathSegments(paymentId: string) {
return `payments/${paymentId}/captures`;
Expand Down Expand Up @@ -97,13 +97,13 @@ export default class PaymentCapturesBinder extends InnerBinder<CaptureData, Capt
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/captures-api/list-captures
*/
public iterate(parameters: Omit<ListParameters, 'limit'>) {
public iterate(parameters: IterateParameters) {
// parameters ?? {} is used here, because in case withParent is used, parameters could be omitted.
const paymentId = this.getParentId((parameters ?? {}).paymentId);
if (!checkId(paymentId, 'payment')) {
throw new ApiError('The payment id is invalid');
}
const { paymentId: _, ...query } = parameters;
return this.networkClient.iterate<CaptureData, Capture>(getPathSegments(paymentId), 'captures', query);
const { valuesPerMinute, paymentId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<CaptureData, Capture>(getPathSegments(paymentId), 'captures', query, valuesPerMinute);
}
}
4 changes: 3 additions & 1 deletion src/binders/payments/captures/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CaptureEmbed } from '../../../data/payments/captures/data';
import { PaginationParameters } from '../../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../../types/parameters';

interface ContextParameters {
paymentId: string;
Expand All @@ -14,3 +14,5 @@ export type ListParameters = ContextParameters &
PaginationParameters & {
embed?: CaptureEmbed[];
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;
8 changes: 4 additions & 4 deletions src/binders/payments/chargebacks/PaymentChargebacksBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import checkId from '../../../plumbing/checkId';
import renege from '../../../plumbing/renege';
import Callback from '../../../types/Callback';
import InnerBinder from '../../InnerBinder';
import { GetParameters, ListParameters } from './parameters';
import { GetParameters, IterateParameters, ListParameters } from './parameters';

function getPathSegments(paymentId: string) {
return `payments/${paymentId}/chargebacks`;
Expand Down Expand Up @@ -91,13 +91,13 @@ export default class PaymentChargebacksBinder extends InnerBinder<ChargebackData
* @since 3.6.0
* @see https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks
*/
public iterate(parameters: Omit<ListParameters, 'limit'>) {
public iterate(parameters: IterateParameters) {
// parameters ?? {} is used here, because in case withParent is used, parameters could be omitted.
const paymentId = this.getParentId((parameters ?? {}).paymentId);
if (!checkId(paymentId, 'payment')) {
throw new ApiError('The payment id is invalid');
}
const { paymentId: _, ...query } = parameters;
return this.networkClient.iterate<ChargebackData, Chargeback>(getPathSegments(paymentId), 'chargebacks', query);
const { valuesPerMinute, paymentId: _, ...query } = parameters ?? {};
return this.networkClient.iterate<ChargebackData, Chargeback>(getPathSegments(paymentId), 'chargebacks', query, valuesPerMinute);
}
}
4 changes: 3 additions & 1 deletion src/binders/payments/chargebacks/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChargebackEmbed } from '../../../data/chargebacks/Chargeback';
import { PaginationParameters } from '../../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../../types/parameters';

interface ContextParameters {
paymentId: string;
Expand All @@ -13,3 +13,5 @@ export type ListParameters = ContextParameters &
PaginationParameters & {
embed?: ChargebackEmbed[];
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;
4 changes: 3 additions & 1 deletion src/binders/payments/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Address, Amount, PaymentMethod } from '../../data/global';
import { Issuer } from '../../data/Issuer';
import { PaymentData, PaymentEmbed, PaymentInclude } from '../../data/payments/data';
import { PaginationParameters } from '../../types/parameters';
import { PaginationParameters, ThrottlingParameters } from '../../types/parameters';
import PickOptional from '../../types/PickOptional';

export type CreateParameters = Pick<PaymentData, 'amount' | 'description' | 'redirectUrl' | 'webhookUrl' | 'customerId' | 'mandateId'> &
Expand Down Expand Up @@ -170,6 +170,8 @@ export type ListParameters = PaginationParameters & {
testmode?: boolean;
};

export type IterateParameters = Omit<ListParameters, 'limit'> & ThrottlingParameters;

export type UpdateParameters = Pick<PaymentData, 'redirectUrl' | 'webhookUrl'> &
PickOptional<PaymentData, 'description' | 'metadata'> & {
/**
Expand Down
Loading

0 comments on commit b1ac614

Please sign in to comment.