Skip to content

Commit c7688e4

Browse files
feat(API Sync): Added Get Credit note and Subscription update with non catalog price (#43)
1 parent 7b77e4e commit c7688e4

26 files changed

+208
-16
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ When we make [non-breaking changes](https://developer.paddle.com/api-reference/a
1212

1313
This means when upgrading minor versions of the SDK, you may notice type errors. You can safely ignore these or fix by adding additional type guards.
1414

15+
## 1.6.0 - 2024-09-16
16+
17+
### Added
18+
19+
- Added `adjustments.getCreditNotePDF()` to [get a credit note for an adjustment](https://developer.paddle.com/api-reference/adjustments/get-credit-note-pdf?utm_source=dx&utm_medium=paddle-node-sdk)
20+
- Added `disposition` query parameter to `adjustments.getCreditNotePDF()` and `transactions.getInvoicePDF()` operations, see [related changelog](https://developer.paddle.com/changelog/2024/invoice-pdf-open-in-browser?utm_source=dx&utm_medium=paddle-node-sdk).
21+
- Added pagination support to `notificationSettings.list()` operation, see [related changelog](https://developer.paddle.com/changelog/2024/notification-settings-pagination?utm_source=dx&utm_medium=paddle-node-sdk).
22+
- Added support for Non-catalog products and prices to the `subscriptions.update()` and `subscriptions.previewUpdate()` operations, see [related changelog](https://developer.paddle.com/changelog/2024/add-custom-items-subscription?utm_source=dx&utm_medium=paddle-node-sdk).
23+
24+
### Fixed
25+
26+
- Marked `notification_id` as optional in `IEventsResponse` interface.
27+
- Fixed a bug where query parameters with false values were not passed correctly to the API.
28+
29+
---
30+
1531
## 1.5.1 - 2024-09-10
1632

1733
### Fixed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@paddle/paddle-node-sdk",
3-
"version": "1.5.1",
3+
"version": "1.6.0",
44
"description": "A Node.js SDK that you can use to integrate Paddle Billing with applications written in server-side JavaScript.",
55
"main": "./dist/cjs/index.js",
66
"module": "./dist/esm/index.js",

src/__tests__/resources/adjustments.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { AdjustmentsResource, ListAdjustmentQueryParameters } from '../../resources';
88
import { getPaddleTestClient } from '../helpers/test-client';
99
import {
10+
AdjustmentMock,
1011
AdjustmentMockResponse,
1112
CreateAdjustmentExpectation,
1213
CreateAdjustmentMock,
@@ -61,4 +62,17 @@ describe('AdjustmentsResource', () => {
6162

6263
expect(convertToSnakeCase(CreateAdjustmentMock)).toEqual(CreateAdjustmentExpectation);
6364
});
65+
66+
test('should get an link to download credit note PDF for an adjustment', async () => {
67+
const adjustmentId = AdjustmentMock.id;
68+
69+
const paddleInstance = getPaddleTestClient();
70+
paddleInstance.get = jest.fn().mockResolvedValue(AdjustmentMockResponse);
71+
72+
const adjustmentResponse = new AdjustmentsResource(paddleInstance);
73+
const creditNotePDF = await adjustmentResponse.getCreditNotePDF(adjustmentId);
74+
75+
expect(paddleInstance.get).toBeCalledWith(`/adjustments/${adjustmentId}/credit-note?`);
76+
expect(creditNotePDF).toBeDefined();
77+
});
6478
});

src/__tests__/resources/notification-settings.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('NotificationSettingsResource', () => {
2525
const notificationsResource = new NotificationSettingsResource(paddleInstance);
2626
const notifications = await notificationsResource.list();
2727

28-
expect(paddleInstance.get).toBeCalledWith('/notification-settings');
28+
expect(paddleInstance.get).toBeCalledWith('/notification-settings?');
2929
expect(notifications.length).toBe(1);
3030
});
3131

src/__tests__/resources/subscriptions.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ describe('SubscriptionsResource', () => {
106106
expect(convertToSnakeCase(UpdateSubscriptionMock)).toEqual(UpdateSubscriptionExpectation);
107107
});
108108

109+
test('should update an existing subscription with non-catalog price', async () => {
110+
const subscriptionId = SubscriptionMock.id;
111+
const subscriptionToBeUpdated: UpdateSubscriptionRequestBody = UpdateSubscriptionMock;
112+
113+
const paddleInstance = getPaddleTestClient();
114+
paddleInstance.patch = jest.fn().mockResolvedValue(SubscriptionMockResponse);
115+
116+
const subscriptionsResource = new SubscriptionsResource(paddleInstance);
117+
const updatedSubscription = await subscriptionsResource.update(subscriptionId, subscriptionToBeUpdated);
118+
119+
expect(paddleInstance.patch).toBeCalledWith(`/subscriptions/${subscriptionId}`, subscriptionToBeUpdated);
120+
expect(updatedSubscription).toBeDefined();
121+
expect(convertToSnakeCase(UpdateSubscriptionMock)).toEqual(UpdateSubscriptionExpectation);
122+
});
123+
109124
test('should preview update an existing subscription', async () => {
110125
const subscriptionId = SubscriptionMock.id;
111126
const subscriptionToBeUpdated: UpdateSubscriptionRequestBody = UpdateSubscriptionMock;

src/__tests__/resources/transactions.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ describe('TransactionsResource', () => {
130130
const transactionsResource = new TransactionsResource(paddleInstance);
131131
const updatedTransaction = await transactionsResource.getInvoicePDF(transactionId);
132132

133-
expect(paddleInstance.get).toBeCalledWith(`/transactions/${transactionId}/invoice`);
133+
expect(paddleInstance.get).toBeCalledWith(`/transactions/${transactionId}/invoice?`);
134134
expect(updatedTransaction).toBeDefined();
135135
});
136136

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
import { type IAdjustmentCreditNotePDF } from '../../types';
8+
9+
export class AdjustmentCreditNotePDF {
10+
public readonly url: string;
11+
12+
constructor(adjustment: IAdjustmentCreditNotePDF) {
13+
this.url = adjustment.url;
14+
}
15+
}

src/entities/adjustment/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './adjustment-item';
1010
export * from './adjustment';
1111
export * from './adjustment-collection';
1212
export * from './adjustment-item-totals';
13+
export * from './adjustment-credit-note-pdf';

src/enums/shared/disposition.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
export type Disposition = 'attachment' | 'inline';

src/enums/shared/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ export * from './error-code';
1919
export * from './payment-type';
2020
export * from './catalog-type';
2121
export * from './available-payment-methods';
22+
export * from './disposition';

src/internal/base/query-parameters.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ function convertCamelCaseToSnakeCase(input: string) {
77
});
88
}
99

10+
function isValidValue<T>(value: T[Extract<keyof T, string>]) {
11+
return value !== undefined && value !== null && value !== '';
12+
}
13+
1014
export class QueryParameters<T> {
1115
constructor(private readonly queryParameters: T) {}
1216
public toQueryString(): string {
1317
const urlSearchParam = new URLSearchParams();
1418
for (const key in this.queryParameters) {
1519
const value = this.queryParameters[key];
16-
if (key && value) {
20+
if (key && isValidValue<T>(value)) {
1721
urlSearchParam.append(convertCamelCaseToSnakeCase(key), `${value}`);
1822
}
1923
}

src/resources/adjustments/index.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@
44
* Changes may be overwritten as part of auto-generation.
55
*/
66

7-
import { AdjustmentCollection, Adjustment } from '../../entities';
7+
import { Adjustment, AdjustmentCollection, AdjustmentCreditNotePDF } from '../../entities';
88
import { type ErrorResponse, type Response } from '../../internal';
9-
import { BaseResource, QueryParameters } from '../../internal/base';
10-
import { type CreateAdjustmentRequestBody, type ListAdjustmentQueryParameters } from './operations';
9+
import { BaseResource, PathParameters, QueryParameters } from '../../internal/base';
10+
import {
11+
type CreateAdjustmentRequestBody,
12+
type ListAdjustmentQueryParameters,
13+
type GetAdjustmentCreditNoteQueryParameters,
14+
} from './operations';
1115
import { type IAdjustmentResponse } from '../../types';
1216

1317
const AdjustmentPaths = {
1418
list: '/adjustments',
1519
create: '/adjustments',
20+
getCreditNotePDF: '/adjustments/{adjustment_id}/credit-note',
1621
} as const;
1722

1823
export * from './operations';
@@ -33,4 +38,23 @@ export class AdjustmentsResource extends BaseResource {
3338

3439
return new Adjustment(data);
3540
}
41+
42+
public async getCreditNotePDF(
43+
adjustmentId: string,
44+
queryParams?: GetAdjustmentCreditNoteQueryParameters,
45+
): Promise<AdjustmentCreditNotePDF> {
46+
const urlWithPathParams = new PathParameters(AdjustmentPaths.getCreditNotePDF, {
47+
adjustment_id: adjustmentId,
48+
}).deriveUrl();
49+
50+
const queryParameters = new QueryParameters(queryParams);
51+
52+
const response = await this.client.get<undefined, Response<AdjustmentCreditNotePDF> | ErrorResponse>(
53+
urlWithPathParams + queryParameters.toQueryString(),
54+
);
55+
56+
const data = this.handleResponse<AdjustmentCreditNotePDF>(response);
57+
58+
return new AdjustmentCreditNotePDF(data);
59+
}
3660
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
import { type Disposition } from '../../../enums';
8+
9+
export interface GetAdjustmentCreditNoteQueryParameters {
10+
disposition?: Disposition;
11+
}

src/resources/adjustments/operations/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66

77
export * from './list-adjustment-query-parameters';
88
export * from './create-adjustment-request-body';
9+
export * from './get-adjustment-credit-note-query-parameters';

src/resources/notification-settings/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
* Changes may be overwritten as part of auto-generation.
55
*/
66

7-
import { BaseResource, PathParameters } from '../../internal/base';
7+
import { BaseResource, PathParameters, QueryParameters } from '../../internal/base';
88
import { type ErrorResponse, type Response } from '../../internal';
99
import { NotificationSettings } from '../../entities';
1010
import { type INotificationSettingsResponse } from '../../types';
11-
import { type CreateNotificationSettingsRequestBody, type UpdateNotificationSettingsRequestBody } from './operations';
11+
import {
12+
type CreateNotificationSettingsRequestBody,
13+
type ListNotificationSettingsQueryParameters,
14+
type UpdateNotificationSettingsRequestBody,
15+
} from './operations';
1216

1317
const NotificationSettingsPaths = {
1418
list: '/notification-settings',
@@ -21,9 +25,11 @@ const NotificationSettingsPaths = {
2125
export * from './operations';
2226

2327
export class NotificationSettingsResource extends BaseResource {
24-
public async list(): Promise<NotificationSettings[]> {
28+
public async list(queryParams?: ListNotificationSettingsQueryParameters): Promise<NotificationSettings[]> {
29+
const queryParameters = new QueryParameters(queryParams);
30+
2531
const response = await this.client.get<undefined, Response<INotificationSettingsResponse[]> | ErrorResponse>(
26-
NotificationSettingsPaths.list,
32+
NotificationSettingsPaths.list + queryParameters.toQueryString(),
2733
);
2834

2935
const data = this.handleResponse<INotificationSettingsResponse[]>(response);

src/resources/notification-settings/operations/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66

77
export * from './create-notification-settings-request-body';
88
export * from './update-notification-settings-request-body';
9+
export * from './list-notification-settings-query-parameters';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
export interface ListNotificationSettingsQueryParameters {
8+
after?: string;
9+
perPage?: number;
10+
orderBy?: string;
11+
active?: boolean;
12+
}

src/resources/transactions/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { BaseResource, PathParameters, QueryParameters } from '../../internal/ba
1010
import {
1111
type CreateTransactionQueryParameters,
1212
type CreateTransactionRequestBody,
13+
type GetTransactionInvoicePdfQueryParameters,
1314
type GetTransactionQueryParameters,
1415
type ListTransactionQueryParameters,
1516
type TransactionPreviewRequestBody,
@@ -87,13 +88,17 @@ export class TransactionsResource extends BaseResource {
8788
return new Transaction(data);
8889
}
8990

90-
public async getInvoicePDF(transactionId: string): Promise<TransactionInvoicePDF> {
91+
public async getInvoicePDF(
92+
transactionId: string,
93+
queryParams?: GetTransactionInvoicePdfQueryParameters,
94+
): Promise<TransactionInvoicePDF> {
95+
const queryParameters = new QueryParameters(queryParams);
9196
const urlWithPathParams = new PathParameters(TransactionPaths.getInvoicePDF, {
9297
transaction_id: transactionId,
9398
}).deriveUrl();
9499

95100
const response = await this.client.get<undefined, Response<ITransactionInvoicePDF> | ErrorResponse>(
96-
urlWithPathParams,
101+
urlWithPathParams + queryParameters.toQueryString(),
97102
);
98103

99104
const data = this.handleResponse<ITransactionInvoicePDF>(response);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
import { type Disposition } from '../../../enums';
8+
9+
export interface GetTransactionInvoicePdfQueryParameters {
10+
disposition?: Disposition;
11+
}

src/resources/transactions/operations/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export * from './create-transaction-request-body';
1111
export * from './get-transaction-query-parameters';
1212
export * from './update-transaction-request-body';
1313
export * from './transaction-preview-request-body';
14+
export * from './get-transaction-invoice-pdf-query-parameters';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
export interface IAdjustmentCreditNotePDF {
8+
url: string;
9+
}

src/types/adjustment/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './adjustments-time-period-response';
88
export * from './adjustments-proration-response';
99
export * from './adjustment-item-response';
1010
export * from './adjustment-response';
11+
export * from './adjustment-credit-note-pdf';

src/types/events/events-response.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121

2222
export interface IEventsResponse<T = object> {
2323
event_id: string;
24-
notification_id: string;
24+
notification_id: string | null;
2525
event_type: string;
2626
occurred_at: string;
2727
data: T;

src/types/subscription/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ export * from './subscription-response';
1616
export * from './subscription-preview-response';
1717
export * from './subscription-preview-update-summary';
1818
export * from './subscription-result-response';
19+
export * from './subscription-update-non-catalog-price-request';

src/types/subscription/subscription-update-item.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,20 @@
33
* Do not make changes to this file.
44
* Changes may be overwritten as part of auto-generation.
55
*/
6+
import { type ISubscriptionUpdateItemCreateWithPriceRequest } from './subscription-update-non-catalog-price-request';
67

7-
export interface ISubscriptionUpdateItem {
8+
interface ISubscriptionUpdateBaseItem {
9+
quantity: number;
10+
}
11+
12+
interface ISubscriptionUpdateItemFromCatalog extends ISubscriptionUpdateBaseItem {
813
priceId: string;
9-
quantity?: number | null;
14+
price?: never;
1015
}
16+
17+
interface ISubscriptionUpdateItemCreateWithPrice extends ISubscriptionUpdateBaseItem {
18+
priceId?: never;
19+
price: ISubscriptionUpdateItemCreateWithPriceRequest;
20+
}
21+
22+
export type ISubscriptionUpdateItem = ISubscriptionUpdateItemFromCatalog | ISubscriptionUpdateItemCreateWithPrice;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* ! Autogenerated code !
3+
* Do not make changes to this file.
4+
* Changes may be overwritten as part of auto-generation.
5+
*/
6+
7+
import { type CreatePriceRequestBody, type CreateProductRequestBody } from '../../resources';
8+
9+
interface ISubscriptionUpdateItemCreateWithPriceBaseRequest
10+
extends Omit<CreatePriceRequestBody, 'type' | 'productId'> {}
11+
12+
interface ISubscriptionUpdateItemCreateWithProductId extends ISubscriptionUpdateItemCreateWithPriceBaseRequest {
13+
productId: string;
14+
product?: never;
15+
}
16+
17+
interface ISubscriptionUpdateItemCreateWithProduct extends ISubscriptionUpdateItemCreateWithPriceBaseRequest {
18+
productId?: never;
19+
product: Omit<CreateProductRequestBody, 'type'>;
20+
}
21+
22+
export type ISubscriptionUpdateItemCreateWithPriceRequest =
23+
| ISubscriptionUpdateItemCreateWithProductId
24+
| ISubscriptionUpdateItemCreateWithProduct;

0 commit comments

Comments
 (0)