Skip to content

Commit c700526

Browse files
committed
Re-enable callback-style calls.
1 parent 3aee0dd commit c700526

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+496
-379
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"dependencies": {
4444
"@typescript-eslint/eslint-plugin": "^2.1.0",
4545
"axios": "^0.19.0",
46+
"jest-bluster": "^1.0.0",
4647
"lodash": "^4.17.15",
4748
"qs": "^6.7.0"
4849
},
@@ -112,7 +113,8 @@
112113
},
113114
"testMatch": [
114115
"<rootDir>/tests/**/*.test.ts"
115-
]
116+
],
117+
"setupFilesAfterEnv": ["jest-bluster"]
116118
},
117119
"config": {
118120
"commitizen": {

src/plumbing/checkId.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ const prefixes = new Map<ResourceKind, string>([
1515
/**
1616
* Returns whether the passed identifier seems plausible (`true`); or is definitely invalid (`false`).
1717
*/
18-
export default function checkId(value: string, resource: ResourceKind): boolean {
19-
return value.startsWith(prefixes.get(resource));
18+
export default function checkId(value: string | undefined, resource: ResourceKind): boolean {
19+
return value != undefined && value.startsWith(prefixes.get(resource)!);
2020
}

src/plumbing/renege.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Allows a promise-style method to be called callback-style.
3+
*
4+
* Behaves in one of two ways, depending on the type of the last argument:
5+
* * If called with a function as the last argument, that argument is considered to be the callback. This function
6+
* calls the passed method, forwarding the original arguments (save for the callback). A settlement of the promise
7+
* returned during that call will be forwarded to the callback. This function then returns `true`.
8+
* * If called with a last argument which is not a function, this function returns `false`.
9+
*/
10+
export default function renege<R>(thisArgument: any, method: (...poppedArguments: any[]) => Promise<R>, ...originalArguments: any[]): boolean {
11+
const candidate = originalArguments.pop();
12+
if (typeof candidate == 'function') {
13+
method.apply(thisArgument, originalArguments)
14+
.then((result: R) => void candidate(null, result), candidate);
15+
return true;
16+
}
17+
return false;
18+
}

src/resources/Resource.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { parse as parseUrl } from 'url';
66

77
function stringifyQuery(input: Record<string, any>): string {
88
return querystring.stringify(
9-
Object.entries(input).reduce((result, [key, value]) => {
9+
Object.entries(input).reduce<Record<string, any>>((result, [key, value]) => {
1010
if (Array.isArray(value)) {
1111
result[key] = value.join(';');
1212
} /* if (Array.isArray(value) == false) */ else {
@@ -33,7 +33,7 @@ export default class Resource<R, T extends R> {
3333
try {
3434
var response: AxiosResponse = await httpClient.post(url, data);
3535
} catch (error) {
36-
throw ApiError.captureStackTrace(error.response);
36+
throw ApiError.createFromResponse(error.response);
3737
}
3838
return this.injectPrototypes(response.data);
3939
},
@@ -87,13 +87,13 @@ export default class Resource<R, T extends R> {
8787
/**
8888
* Injects `nextPage`, `nextPageCursor`, `previousPage`, and `previousPageCursor` into the passed list.
8989
*/
90-
protected injectPaginationHelpers(
90+
protected injectPaginationHelpers<P>(
9191
input: Omit<List<T>, 'nextPage' | 'nextPageCursor' | 'previousPage' | 'previousPageCursor'>,
92-
list: (parameters: Record<string, any>) => Promise<List<T>>,
93-
selfParameters: Record<string, any>,
92+
list: (parameters: P) => Promise<List<T>>,
93+
selfParameters: P,
9494
): List<T> {
9595
const { links } = input;
96-
let nextPage: () => Promise<List<T>> | undefined;
96+
let nextPage: (() => Promise<List<T>>) | undefined;
9797
let nextPageCursor: string | undefined;
9898
if (links.next != null) {
9999
const { query } = parseUrl(links.next.href, true);
@@ -103,7 +103,7 @@ export default class Resource<R, T extends R> {
103103
});
104104
nextPageCursor = query.from as string;
105105
}
106-
let previousPage: () => Promise<List<T>> | undefined;
106+
let previousPage: (() => Promise<List<T>>) | undefined;
107107
let previousPageCursor: string | undefined;
108108
if (links.previous != null) {
109109
const { query } = parseUrl(links.previous.href, true);

src/resources/chargebacks/ChargebacksResource.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import ParentedResource from '../ParentedResource';
22
import Chargeback, { ChargebackData, injectPrototypes } from '../../data/chargebacks/Chargeback';
33
import List from '../../data/list/List';
44
import { ListParameters } from './parameters';
5+
import renege from '../../plumbing/renege';
6+
import Callback from '../../types/Callback';
57

68
/**
79
* The `chargebacks` resource
@@ -55,8 +57,11 @@ export default class ChargebacksResource extends ParentedResource<ChargebackData
5557
*
5658
* @public ✓ This method is part of the public API
5759
*/
58-
public async list(parameters: ListParameters = {}): Promise<List<Chargeback>> {
59-
const result = await this.network.list(this.getResourceUrl(), 'chargebacks', parameters);
60-
return this.injectPaginationHelpers(result, this.list, parameters);
60+
public list(parameters?: ListParameters): Promise<List<Chargeback>>;
61+
public list(parameters: ListParameters, callback: Callback<List<Chargeback>>): void;
62+
public list(parameters: ListParameters = {}) {
63+
if (renege(this, this.list, ...arguments)) return;
64+
return this.network.list(this.getResourceUrl(), 'chargebacks', parameters)
65+
.then(result => this.injectPaginationHelpers(result, this.list, parameters));
6166
}
6267
}

src/resources/chargebacks/parameters.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CommonListParameters } from '../../types/parameters';
2-
import { PaymentChargebackEmbed } from '../../types/payment/chargeback';
2+
import { PaymentChargebackEmbed } from '../../data/chargebacks/Chargeback';
33

44
export type ListParameters = CommonListParameters & {
55
embed?: PaymentChargebackEmbed[];

src/resources/customers/CustomersResource.ts

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import List from '../../data/list/List';
22
import Customer, { CustomerData, injectPrototypes } from '../../data/customers/Customer';
33
import Resource from '../Resource';
4-
import { CreateParameters, ContextParameters, ListParameters, UpdateParameters } from './parameters';
4+
import { CreateParameters, GetParameters, ListParameters, UpdateParameters, DeleteParameters } from './parameters';
55
import checkId from '../../plumbing/checkId';
66
import ApiError from '../../errors/ApiError';
7+
import renege from '../../plumbing/renege';
8+
import Callback from '../../types/Callback';
79

810
/**
911
* The `Customers` resource
@@ -72,7 +74,10 @@ export default class CustomersResource extends Resource<CustomerData, Customer>
7274
*
7375
* @public ✓ This method is part of the public API
7476
*/
75-
public create(parameters: CreateParameters): Promise<Customer> {
77+
public create(parameters: CreateParameters): Promise<Customer>;
78+
public create(parameters: CreateParameters, callback: Callback<Customer>): void;
79+
public create(parameters: CreateParameters) {
80+
if (renege(this, this.create, ...arguments)) return;
7681
return this.network.post(this.getResourceUrl(), parameters);
7782
}
7883

@@ -92,7 +97,10 @@ export default class CustomersResource extends Resource<CustomerData, Customer>
9297
*
9398
* @public ✓ This method is part of the public API
9499
*/
95-
public get(id: string, parameters?: ContextParameters): Promise<Customer> {
100+
public get(id: string, parameters?: GetParameters): Promise<Customer>;
101+
public get(id: string, parameters: GetParameters, callback: Callback<Customer>): void;
102+
public get(id: string, parameters?: GetParameters) {
103+
if (renege(this, this.get, ...arguments)) return;
96104
if (!checkId(id, 'customer')) {
97105
throw new ApiError('The customer id is invalid');
98106
}
@@ -114,9 +122,12 @@ export default class CustomersResource extends Resource<CustomerData, Customer>
114122
*
115123
* @public ✓ This method is part of the public API
116124
*/
117-
public async list(parameters: ListParameters = {}): Promise<List<Customer>> {
118-
const result = await this.network.list(this.getResourceUrl(), 'customers', parameters);
119-
return this.injectPaginationHelpers(result, this.list, parameters);
125+
public list(parameters?: ListParameters): Promise<List<Customer>>;
126+
public list(parameters: ListParameters, callback: Callback<List<Customer>>): void;
127+
public list(parameters: ListParameters = {}) {
128+
if (renege(this, this.list, ...arguments)) return;
129+
return this.network.list(this.getResourceUrl(), 'customers', parameters)
130+
.then(result => this.injectPaginationHelpers(result, this.list, parameters));
120131
}
121132

122133
/**
@@ -135,7 +146,10 @@ export default class CustomersResource extends Resource<CustomerData, Customer>
135146
*
136147
* @public ✓ This method is part of the public API
137148
*/
138-
public update(id: string, parameters: UpdateParameters): Promise<Customer> {
149+
public update(id: string, parameters: UpdateParameters): Promise<Customer>;
150+
public update(id: string, parameters: UpdateParameters, callback: Callback<Customer>): void;
151+
public update(id: string, parameters: UpdateParameters) {
152+
if (renege(this, this.update, ...arguments)) return;
139153
if (!checkId(id, 'customer')) {
140154
throw new ApiError('The customer id is invalid');
141155
}
@@ -158,7 +172,10 @@ export default class CustomersResource extends Resource<CustomerData, Customer>
158172
*
159173
* @public ✓ This method is part of the public API
160174
*/
161-
public delete(id: string, parameters?: ContextParameters): Promise<true> {
175+
public delete(id: string, parameters?: DeleteParameters): Promise<true>;
176+
public delete(id: string, parameters: DeleteParameters, callback: Callback<true>): void
177+
public delete(id: string, parameters?: DeleteParameters) {
178+
if (renege(this, this.delete, ...arguments)) return;
162179
if (!checkId(id, 'customer')) {
163180
throw new ApiError('The customer id is invalid');
164181
}

src/resources/customers/mandates/CustomersMandatesResource.ts

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import ParentedResource from '../../ParentedResource';
22
import { MandateData } from '../../../data/customers/mandates/data';
33
import Mandate, { injectPrototypes } from '../../../data/customers/mandates/Mandate';
4-
import { CreateParameters, ContextParameters, ListParameters } from './parameters';
4+
import { CreateParameters, GetParameters, ListParameters, RevokeParameters } from './parameters';
55
import checkId from '../../../plumbing/checkId';
66
import ApiError from '../../../errors/ApiError';
77
import List from '../../../data/list/List';
8+
import renege from '../../../plumbing/renege';
9+
import Callback from '../../../types/Callback';
810

911
/**
1012
* The `customers_mandates` resource
@@ -81,13 +83,16 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
8183
*
8284
* @public ✓ This method is part of the public API
8385
*/
84-
public create(parameters: CreateParameters): Promise<Mandate> {
86+
public create(parameters: CreateParameters): Promise<Mandate>;
87+
public create(parameters: CreateParameters, callback: Callback<Mandate>): void;
88+
public create(parameters: CreateParameters) {
89+
if (renege(this, this.create, ...arguments)) return;
8590
const customerId = this.getParentId(parameters.customerId);
8691
if (!checkId(customerId, 'customer')) {
8792
throw new ApiError('The customer id is invalid');
8893
}
8994
const { customerId: _, ...data } = parameters;
90-
return this.network.post(this.getResourceUrl(customerId), data);
95+
return this.network.post(this.getResourceUrl(customerId!), data);
9196
}
9297

9398
/**
@@ -106,7 +111,10 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
106111
*
107112
* @public ✓ This method is part of the public API
108113
*/
109-
public get(id: string, parameters: ContextParameters): Promise<Mandate> {
114+
public get(id: string, parameters: GetParameters): Promise<Mandate>;
115+
public get(id: string, parameters: GetParameters, callback: Callback<Mandate>): void;
116+
public get(id: string, parameters: GetParameters) {
117+
if (renege(this, this.get, ...arguments)) return;
110118
if (!checkId(id, 'mandate')) {
111119
throw new ApiError('The customers_mandate id is invalid');
112120
}
@@ -116,7 +124,7 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
116124
throw new ApiError('The customer id is invalid');
117125
}
118126
const { customerId: _, ...query } = parameters || {};
119-
return this.network.get(`${this.getResourceUrl(customerId)}/${id}`, query);
127+
return this.network.get(`${this.getResourceUrl(customerId!)}/${id}`, query);
120128
}
121129

122130
/**
@@ -134,15 +142,18 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
134142
*
135143
* @public ✓ This method is part of the public API
136144
*/
137-
public async list(parameters: ListParameters): Promise<List<Mandate>> {
145+
public list(parameters: ListParameters): Promise<List<Mandate>>;
146+
public list(parameters: ListParameters, callback: Callback<List<Mandate>>): void;
147+
public list(parameters: ListParameters) {
148+
if (renege(this, this.list, ...arguments)) return;
138149
// parameters || {} is used here, because in case withParent is used, parameters could be omitted.
139150
const customerId = this.getParentId((parameters || {}).customerId);
140151
if (!checkId(customerId, 'customer')) {
141152
throw new ApiError('The customer id is invalid');
142153
}
143154
const { customerId: _, ...query } = parameters || {};
144-
const result = await this.network.list(this.getResourceUrl(customerId), 'mandates', query);
145-
return this.injectPaginationHelpers(result, this.list, parameters || {});
155+
return this.network.list(this.getResourceUrl(customerId!), 'mandates', query)
156+
.then(result => this.injectPaginationHelpers(result, this.list, parameters || {}));
146157
}
147158

148159
/**
@@ -161,7 +172,10 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
161172
*
162173
* @public ✓ This method is part of the public API
163174
*/
164-
public revoke(id: string, parameters: ContextParameters): Promise<true> {
175+
public revoke(id: string, parameters: RevokeParameters): Promise<true>;
176+
public revoke(id: string, parameters: RevokeParameters, callback: Callback<true>): void;
177+
public revoke(id: string, parameters: RevokeParameters) {
178+
if (renege(this, this.revoke, ...arguments)) return;
165179
if (!checkId(id, 'mandate')) {
166180
throw new ApiError('The customers_mandate id is invalid');
167181
}
@@ -171,6 +185,6 @@ export default class CustomersMandatesResource extends ParentedResource<MandateD
171185
throw new ApiError('The customer is invalid');
172186
}
173187
const { customerId: _, ...query } = parameters || {};
174-
return this.network.delete(`${this.getResourceUrl(customerId)}/${id}`) as Promise<true>;
188+
return this.network.delete(`${this.getResourceUrl(customerId!)}/${id}`) as Promise<true>;
175189
}
176190
}

src/resources/customers/mandates/parameters.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { MandateData } from '../../../data/customers/mandates/data';
22
import { CommonListParameters } from '../../../types/parameters';
33

4-
export interface ContextParameters {
4+
interface ContextParameters {
55
customerId: string;
66
testmode?: boolean;
77
}
@@ -15,4 +15,8 @@ export type CreateParameters = ContextParameters &
1515
mandateReference?: string;
1616
};
1717

18+
export type GetParameters = ContextParameters;
19+
1820
export type ListParameters = ContextParameters & CommonListParameters;
21+
22+
export type RevokeParameters = ContextParameters;

src/resources/customers/parameters.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ import { CustomerData } from '../../data/customers/Customer';
22
import { PickOptional } from '../../types/PickOptional';
33
import { CommonListParameters } from '../../types/parameters';
44

5-
export interface ContextParameters {
5+
interface ContextParameters {
66
testmode?: boolean;
77
}
88

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

11+
export type GetParameters = ContextParameters;
12+
1113
export type ListParameters = ContextParameters & CommonListParameters;
1214

1315
export type UpdateParameters = ContextParameters & PickOptional<CustomerData, 'name' | 'email' | 'locale' | 'metadata'>;
16+
17+
export type DeleteParameters = ContextParameters;

src/resources/customers/payments/CustomersPaymentsResource.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import ParentedResource from '../../ParentedResource';
22
import { PaymentData } from '../../../data/payments/data';
33
import Payment, { injectPrototypes } from '../../../data/payments/Payment';
4-
import { CreateParameters, ContextParameters } from './parameters';
4+
import { CreateParameters, ListParameters } from './parameters';
55
import checkId from '../../../plumbing/checkId';
66
import ApiError from '../../../errors/ApiError';
77
import List from '../../../data/list/List';
8+
import renege from '../../../plumbing/renege';
9+
import Callback from '../../../types/Callback';
810

911
/**
1012
* The `customers_payments` resource.
@@ -57,13 +59,16 @@ export default class CustomersPaymentsResource extends ParentedResource<PaymentD
5759
*
5860
* @public ✓ This method is part of the public API
5961
*/
60-
public create(parameters: CreateParameters): Promise<Payment> {
62+
public create(parameters: CreateParameters): Promise<Payment>;
63+
public create(parameters: CreateParameters, callback: Callback<Payment>): void;
64+
public create(parameters: CreateParameters) {
65+
if (renege(this, this.create, ...arguments)) return;
6166
const customerId = this.getParentId(parameters.customerId);
6267
if (!checkId(customerId, 'customer')) {
6368
throw new ApiError('The customer id is invalid');
6469
}
6570
const { customerId: _, ...data } = parameters;
66-
return this.network.post(this.getResourceUrl(customerId), data);
71+
return this.network.post(this.getResourceUrl(customerId!), data);
6772
}
6873

6974
/**
@@ -81,14 +86,17 @@ export default class CustomersPaymentsResource extends ParentedResource<PaymentD
8186
*
8287
* @public ✓ This method is part of the public API
8388
*/
84-
public async list(parameters: ContextParameters): Promise<List<Payment>> {
89+
public list(parameters: ListParameters): Promise<List<Payment>>;
90+
public list(parameters: ListParameters, callback: Callback<List<Payment>>): void;
91+
public list(parameters: ListParameters) {
92+
if (renege(this, this.list, ...arguments)) return;
8593
// parameters || {} is used here, because in case withParent is used, parameters could be omitted.
8694
const customerId = this.getParentId((parameters || {}).customerId);
8795
if (!checkId(customerId, 'customer')) {
8896
throw new ApiError('The customer id is invalid');
8997
}
9098
const { customerId: _, ...query } = parameters || {};
91-
const result = await this.network.list(this.getResourceUrl(customerId), 'payments', query);
92-
return this.injectPaginationHelpers(result, this.list, parameters || {});
99+
return this.network.list(this.getResourceUrl(customerId!), 'payments', query)
100+
.then(result => this.injectPaginationHelpers(result, this.list, parameters || {}));
93101
}
94102
}

0 commit comments

Comments
 (0)